JAL-1136 JAL-811 JAL-812 store/recover autocalc alignment annotation based on calcId...
[jalview.git] / src / jalview / gui / Jalview2XML.java
old mode 100755 (executable)
new mode 100644 (file)
index e1510de..7fb7f0b
@@ -1,18 +1,18 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
- * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
- * 
+ * 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
+ *
  * 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/>.
  */
 package jalview.gui;
@@ -29,31 +29,38 @@ import javax.swing.*;
 
 import org.exolab.castor.xml.*;
 
-import uk.ac.vamsas.objects.utils.MapList;
 import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
 import jalview.schemabinding.version2.*;
 import jalview.schemes.*;
-import jalview.structure.StructureSelectionManager;
+import jalview.util.Platform;
 import jalview.util.jarInputStreamProvider;
+import jalview.ws.jws2.AAConsClient;
+import jalview.ws.jws2.Jws2Discoverer;
+import jalview.ws.jws2.dm.AAConsSettings;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.AutoCalcSetting;
+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$
+ * @version $Revision: 1.134 $
  */
 public class Jalview2XML
 {
   /**
    * create/return unique hash string for sq
-   * 
+   *
    * @param sq
    * @return new or existing unique string for sq
    */
@@ -259,7 +266,7 @@ public class Jalview2XML
 
   /**
    * Writes a jalview project archive to the given Jar output stream.
-   * 
+   *
    * @param jout
    */
   public void SaveState(JarOutputStream jout)
@@ -400,7 +407,7 @@ public class Jalview2XML
   /**
    * create a JalviewModel from an algnment view and marshall it to a
    * JarOutputStream
-   * 
+   *
    * @param ap
    *          panel to create jalview model for
    * @param fileName
@@ -425,9 +432,9 @@ public class Jalview2XML
     object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
     object.setVersion(jalview.bin.Cache.getProperty("VERSION"));
 
-    jalview.datamodel.AlignmentI jal = av.alignment;
+    jalview.datamodel.AlignmentI jal = av.getAlignment();
 
-    if (av.hasHiddenRows)
+    if (av.hasHiddenRows())
     {
       jal = jal.getHiddenSequences().getFullAlignment();
     }
@@ -457,6 +464,7 @@ public class Jalview2XML
     }
 
     JSeq jseq;
+    Set<String> calcIdSet=new HashSet<String>();
 
     // SAVE SEQUENCES
     String id = "";
@@ -496,15 +504,13 @@ public class Jalview2XML
 
       jseq.setId(id); // jseq id should be a string not a number
 
-      if (av.hasHiddenRows)
+      if (av.hasHiddenRows())
       {
-        jseq.setHidden(av.alignment.getHiddenSequences().isHidden(jds));
+        jseq.setHidden(av.getAlignment().getHiddenSequences().isHidden(jds));
 
-        if (av.hiddenRepSequences != null
-                && av.hiddenRepSequences.containsKey(jal.getSequenceAt(i)))
+        if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
         {
-          jalview.datamodel.SequenceI[] reps = ((jalview.datamodel.SequenceGroup) av.hiddenRepSequences
-                  .get(jal.getSequenceAt(i))).getSequencesInOrder(jal);
+          jalview.datamodel.SequenceI[] reps = av.getRepresentedSequences(jal.getSequenceAt(i)).getSequencesInOrder(jal);
 
           for (int h = 0; h < reps.length; h++)
           {
@@ -580,7 +586,6 @@ public class Jalview2XML
           {
             if (frames[f] instanceof AppJmol)
             {
-              // TODO: revise schema to allow many:one PDB id binding to viewer
               jmol = (AppJmol) frames[f];
               for (int peid = 0; peid < jmol.jmb.pdbentry.length; peid++)
               {
@@ -612,7 +617,8 @@ public class Jalview2XML
 
                 for (int smap = 0; smap < jmol.jmb.sequence[peid].length; smap++)
                 {
-                  if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
+//                  if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
+                  if (jds==jmol.jmb.sequence[peid][smap])
                   {
                     StructureState state = new StructureState();
                     state.setVisible(true);
@@ -621,6 +627,10 @@ public class Jalview2XML
                     state.setWidth(jmol.getWidth());
                     state.setHeight(jmol.getHeight());
                     state.setViewId(jmol.getViewId());
+                    state.setAlignwithAlignPanel(jmol.isUsedforaligment(ap));
+                    state.setColourwithAlignPanel(jmol
+                            .isUsedforcolourby(ap));
+                    state.setColourByJmol(jmol.isColouredByJmol());
                     if (!jmolViewIds.contains(state.getViewId()))
                     {
                       // Make sure we only store a Jmol state once in each XML
@@ -702,9 +712,9 @@ public class Jalview2XML
       jms.addJSeq(jseq);
     }
 
-    if (av.hasHiddenRows)
+    if (av.hasHiddenRows())
     {
-      jal = av.alignment;
+      jal = av.getAlignment();
     }
     // SAVE MAPPINGS
     if (jal.getCodonFrames() != null && jal.getCodonFrames().length > 0)
@@ -760,7 +770,7 @@ public class Jalview2XML
           {
             TreePanel tp = (TreePanel) frames[t];
 
-            if (tp.treeCanvas.av.alignment == jal)
+            if (tp.treeCanvas.av.getAlignment() == jal)
             {
               Tree tree = new Tree();
               tree.setTitle(tp.getTitle());
@@ -788,7 +798,6 @@ public class Jalview2XML
         }
       }
     }
-
     // SAVE ANNOTATIONS
     /**
      * store forward refs from an annotationRow to any groups
@@ -832,18 +841,13 @@ public class Jalview2XML
           }
           an.setGroupRef(groupIdr.toString());
         }
-        if (aa[i] == av.quality || aa[i] == av.conservation
-                || aa[i] == av.consensus || aa[i].autoCalculated)
-        {
-          // new way of indicating autocalculated annotation -
-          an.setAutoCalculated(aa[i].autoCalculated);
-          // write a stub for this annotation - indicate presence of autocalc
-          // rows
-          an.setLabel(aa[i].label);
-          an.setGraph(true);
-          vamsasSet.addAnnotation(an);
-          continue;
-        }
+
+        // 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)
         {
@@ -865,10 +869,24 @@ public class Jalview2XML
         }
 
         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)
         {
@@ -902,6 +920,13 @@ public class Jalview2XML
             }
 
             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
@@ -915,13 +940,11 @@ public class Jalview2XML
     if (jal.getGroups() != null)
     {
       JGroup[] groups = new JGroup[jal.getGroups().size()];
-
-      for (int i = 0; i < groups.length; i++)
+      int i = -1;
+      for (jalview.datamodel.SequenceGroup sg:jal.getGroups())
       {
-        groups[i] = new JGroup();
+        groups[++i] = new JGroup();
 
-        jalview.datamodel.SequenceGroup sg = (jalview.datamodel.SequenceGroup) jal
-                .getGroups().elementAt(i);
         groups[i].setStart(sg.getStartRes());
         groups[i].setEnd(sg.getEndRes());
         groups[i].setName(sg.getName());
@@ -1107,48 +1130,51 @@ public class Jalview2XML
       Vector settingsAdded = new Vector();
       Object gstyle = null;
       GraduatedColor gcol = null;
-      for (int ro = 0; ro < renderOrder.length; ro++)
+      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());
-        }
-        else
+        for (int ro = 0; ro < renderOrder.length; ro++)
         {
-          setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
-                  .getColour(renderOrder[ro]).getRGB());
-        }
+          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);
+          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]);
         }
-        fs.addSetting(setting);
-        settingsAdded.addElement(renderOrder[ro]);
       }
 
       // Make sure we save none displayed feature settings
-      Enumeration en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
-              .keys();
-      while (en.hasMoreElements())
+      Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
+              .keySet().iterator();
+      while (en.hasNext())
       {
-        String key = en.nextElement().toString();
+        String key = en.next().toString();
         if (settingsAdded.contains(key))
         {
           continue;
@@ -1169,11 +1195,11 @@ public class Jalview2XML
         fs.addSetting(setting);
         settingsAdded.addElement(key);
       }
-      en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups.keys();
+      en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups.keySet().iterator();
       Vector groupsAdded = new Vector();
-      while (en.hasMoreElements())
+      while (en.hasNext())
       {
-        String grp = en.nextElement().toString();
+        String grp = en.next().toString();
         if (groupsAdded.contains(grp))
         {
           continue;
@@ -1189,7 +1215,7 @@ public class Jalview2XML
 
     }
 
-    if (av.hasHiddenColumns)
+    if (av.hasHiddenColumns())
     {
       if (av.getColumnSelection() == null
               || av.getColumnSelection().getHiddenColumns() == null)
@@ -1210,6 +1236,15 @@ public class Jalview2XML
         }
       }
     }
+    if (calcIdSet.size()>0)
+    {
+      for (String calcId:calcIdSet)
+      {
+        if (calcId.trim().length()>0) {
+          view.addCalcIdParam(createCalcIdParam(calcId, av));
+        }
+      }
+    }
 
     jms.addViewport(view);
 
@@ -1241,6 +1276,84 @@ public class Jalview2XML
     return object;
   }
 
+  private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
+  {
+    AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
+    if (settings != null)
+    {
+      CalcIdParam vCalcIdParam = new CalcIdParam();
+      vCalcIdParam.setCalcId(calcId);
+      vCalcIdParam.addServiceURL(settings.getServiceURI());
+      // generic URI allowing a third party to resolve another instance of the
+      // service used for this calculation
+      for (String urls:settings.getServiceURLs())
+      {
+        vCalcIdParam.addServiceURL(urls);
+      }
+      vCalcIdParam.setVersion("1.0");
+      if (settings.getPreset() != null)
+      {
+        WsParamSetI setting = settings.getPreset();
+        vCalcIdParam.setName(setting.getName());
+        vCalcIdParam.setDescription(setting.getDescription());
+      }
+      else
+      {
+        vCalcIdParam.setName("");
+        vCalcIdParam.setDescription("Last used parameters");
+      }
+      // need to be able to recover 1) settings 2) user-defined presets or
+      // recreate settings from preset 3) predefined settings provided by
+      // service - or settings that can be transferred (or discarded)
+      vCalcIdParam.setParameters(settings
+              .getWsParamFile().replace("\n", "|\\n|"));
+      vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
+      // todo - decide if updateImmediately is needed for any projects.
+
+      return vCalcIdParam;
+    }
+    return null;
+  }
+
+  private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
+          AlignViewport av)
+  {
+    if (calcIdParam.getVersion().equals("1.0"))
+    {
+      Jws2Instance service=Jws2Discoverer.getDiscoverer().getPreferredServiceFor(calcIdParam.getServiceURL());
+      if (service!=null)
+      {
+        WsParamSetI parmSet=null;
+        try {
+          parmSet = service.getParamStore().parseServiceParameterFile(calcIdParam.getName(), calcIdParam.getDescription(), calcIdParam.getServiceURL(), calcIdParam.getParameters().replace("|\\n|", "\n"));
+        } catch (IOException x)
+        {
+          warn("Couldn't parse parameter data for "+calcIdParam.getCalcId(), x);
+          return false;
+        }
+        List<ArgumentI> argList=null;
+        if (calcIdParam.getName().length()>0) {
+          parmSet = service.getParamStore().getPreset(calcIdParam.getName());
+          if (parmSet!=null)
+          {
+            // TODO : check we have a good match with settings in AACons - otherwise we'll need to create a new preset
+          }
+        }
+        else {
+          argList = parmSet.getArguments();
+          parmSet=null;
+        }
+        AAConsSettings settings = new AAConsSettings(calcIdParam.isAutoUpdate(), service, parmSet, argList);
+        av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings, calcIdParam.isNeedsUpdate());
+        return true;
+      } else {
+        warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
+        return false;
+      }
+    }
+    throw new Error("Unsupported Version for calcIdparam "
+            + calcIdParam.toString());
+  }
   /**
    * External mapping between jalview objects and objects yielding a valid and
    * unique object ID string. This is null for normal Jalview project IO, but
@@ -1252,7 +1365,7 @@ public class Jalview2XML
   /**
    * Construct a unique ID for jvobj using either existing bindings or if none
    * exist, the result of the hashcode call for the object.
-   * 
+   *
    * @param jvobj
    *          jalview data object
    * @return unique ID for referring to jvobj
@@ -1283,7 +1396,7 @@ public class Jalview2XML
 
   /**
    * return local jalview object mapped to ID, if it exists
-   * 
+   *
    * @param idcode
    *          (may be null)
    * @return null or object bound to idcode
@@ -1519,7 +1632,7 @@ public class Jalview2XML
 
   /**
    * Load a jalview project archive from a jar file
-   * 
+   *
    * @param file
    *          - HTTP URL or filename
    */
@@ -1563,6 +1676,7 @@ public class Jalview2XML
     return new jarInputStreamProvider()
     {
 
+      @Override
       public JarInputStream getJarInputStream() throws IOException
       {
         if (_url != null)
@@ -1575,6 +1689,7 @@ public class Jalview2XML
         }
       }
 
+      @Override
       public String getFilename()
       {
         return file;
@@ -1587,7 +1702,7 @@ public class Jalview2XML
    * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
    * themselves. Any null fields will be initialised with default values,
    * non-null fields are left alone.
-   * 
+   *
    * @param jprovider
    * @return
    */
@@ -1739,6 +1854,7 @@ public class Jalview2XML
       {
         javax.swing.SwingUtilities.invokeLater(new Runnable()
         {
+          @Override
           public void run()
           {
             JOptionPane.showInternalMessageDialog(Desktop.desktop,
@@ -1763,7 +1879,7 @@ public class Jalview2XML
    * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
    * sync if this is set to true.
    */
-  private boolean updateLocalViews = false;
+  private final boolean updateLocalViews = false;
 
   String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
   {
@@ -1807,9 +1923,9 @@ public class Jalview2XML
         }
         ;
         out.close();
-
-        alreadyLoadedPDB.put(pdbId, outFile.getAbsolutePath());
-        return outFile.getAbsolutePath();
+        String t=outFile.getAbsolutePath();
+        alreadyLoadedPDB.put(pdbId, t);
+        return t;
       }
       else
       {
@@ -1823,9 +1939,28 @@ public class Jalview2XML
     return null;
   }
 
+  private class JvAnnotRow
+  {
+    public JvAnnotRow(int i, AlignmentAnnotation jaa)
+    {
+      order = i;
+      template = jaa;
+    }
+
+    /**
+     * persisted version of annotation row from which to take vis properties
+     */
+    public jalview.datamodel.AlignmentAnnotation template;
+
+    /**
+     * original position of the annotation row in the alignment
+     */
+    public int order;
+  }
+
   /**
    * Load alignment frame from jalview XML DOM object
-   * 
+   *
    * @param object
    *          DOM
    * @param file
@@ -1863,7 +1998,7 @@ public class Jalview2XML
 
       if (seqRefIds.get(seqId) != null)
       {
-        tmpseqs.add((jalview.datamodel.Sequence) seqRefIds.get(seqId));
+        tmpseqs.add(seqRefIds.get(seqId));
         multipleView = true;
       }
       else
@@ -1886,7 +2021,7 @@ public class Jalview2XML
           hiddenSeqs = new Vector();
         }
 
-        hiddenSeqs.addElement((jalview.datamodel.Sequence) seqRefIds
+        hiddenSeqs.addElement(seqRefIds
                 .get(seqId));
       }
 
@@ -2055,11 +2190,11 @@ public class Jalview2XML
 
     // ////////////////////////////////
     // LOAD ANNOTATIONS
-    boolean hideQuality = true, hideConservation = true, hideConsensus = true;
+    ArrayList<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
     /**
      * store any annotations which forward reference a group's ID
      */
-    Hashtable groupAnnotRefs = new Hashtable();
+    Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
 
     if (vamsasSet.getAnnotationCount() > 0)
     {
@@ -2067,22 +2202,29 @@ public class Jalview2XML
 
       for (int i = 0; i < an.length; i++)
       {
-        // set visibility for automatic annotation for this view
-        if (an[i].getLabel().equals("Quality"))
-        {
-          hideQuality = false;
-          continue;
-        }
-        else if (an[i].getLabel().equals("Conservation"))
-        {
-          hideConservation = false;
-          continue;
+        /**
+         * test if annotation is automatically calculated for this view only
+         */
+        boolean autoForView = false;
+        if (an[i].getLabel().equals("Quality")
+                || an[i].getLabel().equals("Conservation")
+                || an[i].getLabel().equals("Consensus"))
+        {
+          // Kludge for pre 2.5 projects which lacked the autocalculated flag
+          autoForView = true;
+          if (!an[i].hasAutoCalculated())
+          {
+            an[i].setAutoCalculated(true);
+          }
         }
-        else if (an[i].getLabel().equals("Consensus"))
+        if (autoForView
+                || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
         {
-          hideConsensus = false;
-          continue;
+          // remove ID - we don't recover annotation from other views for
+          // view-specific annotation
+          an[i].setId(null);
         }
+
         // set visiblity for other annotation in this view
         if (an[i].getId() != null
                 && annotationIds.containsKey(an[i].getId()))
@@ -2105,7 +2247,6 @@ public class Jalview2XML
         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)
@@ -2135,8 +2276,13 @@ public class Jalview2XML
 
         if (an[i].getGraph())
         {
+          float llim = 0, hlim = 0;
+          // if (autoForView || an[i].isAutoCalculated()) {
+          // hlim=11f;
+          // }
           jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
-                  an[i].getDescription(), anot, 0, 0, an[i].getGraphType());
+                  an[i].getDescription(), anot, llim, hlim,
+                  an[i].getGraphType());
 
           jaa.graphGroup = an[i].getGraphGroup();
 
@@ -2148,33 +2294,49 @@ public class Jalview2XML
                     an[i].getThresholdLine().getColour())));
 
           }
-
+          if (autoForView || an[i].isAutoCalculated())
+          {
+            // Hardwire the symbol display line to ensure that labels for
+            // histograms are displayed
+            jaa.hasText = true;
+          }
         }
         else
         {
           jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
                   an[i].getDescription(), anot);
         }
-        // register new annotation
-        if (an[i].getId() != null)
-        {
-          annotationIds.put(an[i].getId(), jaa);
-          jaa.annotationId = an[i].getId();
-        }
-        // recover sequence association
-        if (an[i].getSequenceRef() != null)
+        if (autoForView)
         {
-          if (al.findName(an[i].getSequenceRef()) != null)
+          // register new annotation
+          if (an[i].getId() != null)
           {
-            jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
-                    1, true);
-            al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
+            annotationIds.put(an[i].getId(), jaa);
+            jaa.annotationId = an[i].getId();
+          }
+          // recover sequence association
+          if (an[i].getSequenceRef() != null)
+          {
+            if (al.findName(an[i].getSequenceRef()) != null)
+            {
+              jaa.createSequenceMapping(
+                      al.findName(an[i].getSequenceRef()), 1, true);
+              al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(
+                      jaa);
+            }
           }
         }
         // and make a note of any group association
         if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
         {
-          groupAnnotRefs.put(an[i].getGroupRef(), jaa);
+          ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
+                  .get(an[i].getGroupRef());
+          if (aal == null)
+          {
+            aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
+            groupAnnotRefs.put(an[i].getGroupRef(), aal);
+          }
+          aal.add(jaa);
         }
 
         if (an[i].hasScore())
@@ -2198,7 +2360,27 @@ public class Jalview2XML
           jaa.autoCalculated = true; // means annotation will be marked for
           // update at end of load.
         }
-        al.addAnnotation(jaa);
+        if (an[i].hasGraphHeight())
+        {
+          jaa.graphHeight = an[i].getGraphHeight();
+        }
+        if (an[i].hasBelowAlignment())
+        {
+          jaa.belowAlignment=an[i].isBelowAlignment();
+        }
+        jaa.setCalcId(an[i].getCalcId());
+
+        if (jaa.autoCalculated)
+        {
+          autoAlan.add(new JvAnnotRow(i, jaa));
+        }
+        else
+        // if (!autoForView)
+        {
+          // add autocalculated group annotation and any user created annotation
+          // for the view
+          al.addAnnotation(jaa);
+        }
       }
     }
 
@@ -2287,11 +2469,29 @@ public class Jalview2XML
         if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
         {
           // re-instate unique group/annotation row reference
-          jalview.datamodel.AlignmentAnnotation jaa = (jalview.datamodel.AlignmentAnnotation) groupAnnotRefs
+          ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
                   .get(groups[i].getId());
-          if (jaa != null)
+          if (jaal != null)
           {
-            jaa.groupRef = sg;
+            for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
+            {
+              jaa.groupRef = sg;
+              if (jaa.autoCalculated)
+              {
+                // match up and try to set group autocalc alignment row for this
+                // annotation
+                if (jaa.label.startsWith("Consensus for "))
+                {
+                  sg.setConsensus(jaa);
+                }
+                // match up and try to set group autocalc alignment row for this
+                // annotation
+                if (jaa.label.startsWith("Conservation for "))
+                {
+                  sg.setConservationRow(jaa);
+                }
+              }
+            }
           }
         }
         al.addGroup(sg);
@@ -2369,9 +2569,8 @@ public class Jalview2XML
 
     if (isnewview)
     {
-      af = loadViewport(file, JSEQ, hiddenSeqs, al, hideConsensus,
-              hideQuality, hideConservation, jms, view, uniqueSeqSetId,
-              viewId);
+      af = loadViewport(file, JSEQ, hiddenSeqs, al, jms, view,
+              uniqueSeqSetId, viewId, autoAlan);
       av = af.viewport;
       ap = af.alignPanel;
     }
@@ -2500,12 +2699,31 @@ public class Jalview2XML
                 jmolViewIds.put(sviewid, new Object[]
                 { new int[]
                 { x, y, width, height }, "",
-                    new Hashtable<String, Object[]>() });
+                    new Hashtable<String, Object[]>(), new boolean[]
+                    { false, false, true } });
+                // Legacy pre-2.7 conversion JAL-823 :
+                // do not assume any view has to be linked for colour by
+                // sequence
               }
-              // TODO: assemble String[] { pdb files }, String[] { id for each
+
+              // assemble String[] { pdb files }, String[] { id for each
               // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
-              // seqs_file 2}} from hash
-              Object[] jmoldat = (Object[]) jmolViewIds.get(sviewid);
+              // seqs_file 2}, boolean[] {
+              // linkAlignPanel,superposeWithAlignpanel}} from hash
+              Object[] jmoldat = jmolViewIds.get(sviewid);
+              ((boolean[]) jmoldat[3])[0] |= ids[p].getStructureState(s)
+                      .hasAlignwithAlignPanel() ? ids[p].getStructureState(
+                      s).getAlignwithAlignPanel() : false;
+              // never colour by linked panel if not specified
+              ((boolean[]) jmoldat[3])[1] |= ids[p].getStructureState(s)
+                      .hasColourwithAlignPanel() ? ids[p]
+                      .getStructureState(s).getColourwithAlignPanel()
+                      : false;
+              // default for pre-2.7 projects is that Jmol colouring is enabled
+              ((boolean[]) jmoldat[3])[2] &= ids[p].getStructureState(s)
+                      .hasColourByJmol() ? ids[p].getStructureState(s)
+                      .getColourByJmol() : true;
+
               if (((String) jmoldat[1]).length() < ids[p]
                       .getStructureState(s).getContent().length())
               {
@@ -2513,22 +2731,33 @@ public class Jalview2XML
                   jmoldat[1] = ids[p].getStructureState(s).getContent();
                 }
               }
-              Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2])
-                      .get(ids[p].getFile());
-              if (seqstrmaps == null)
+              if (ids[p].getFile() != null)
               {
-                ((Hashtable) jmoldat[2]).put(
-                        new File(ids[p].getFile()).toString(),
-                        seqstrmaps = new Object[]
-                        { pdbFile, ids[p].getId(), new Vector(),
-                            new Vector() });
+                File mapkey=new File(ids[p].getFile());
+                Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2])
+                        .get(mapkey);
+                if (seqstrmaps == null)
+                {
+                  ((Hashtable) jmoldat[2]).put(
+                          mapkey,
+                          seqstrmaps = new Object[]
+                          { pdbFile, ids[p].getId(), new Vector(),
+                              new Vector() });
+                }
+                if (!((Vector) seqstrmaps[2]).contains(seq))
+                {
+                  ((Vector) seqstrmaps[2]).addElement(seq);
+                  // ((Vector)seqstrmaps[3]).addElement(n) :
+                  // in principle, chains
+                  // should be stored here : do we need to
+                  // TODO: store and recover seq/pdb_id :
+                  // chain mappings
+                }
               }
-              if (!((Vector) seqstrmaps[2]).contains(seq))
+              else
               {
-                ((Vector) seqstrmaps[2]).addElement(seq);
-                // ((Vector)seqstrmaps[3]).addElement(n) : in principle, chains
-                // should be stored here : do we need to
-                // TODO: store and recover seq/pdb_id : chain mappings
+                errorMessage = ("The Jmol views in this project were imported\nfrom an older version of Jalview.\nPlease review the sequence colour associations\nin the Colour by section of the Jmol View menu.\n\nIn the case of problems, see note at\nhttp://issues.jalview.org/browse/JAL-747");
+                warn(errorMessage);
               }
             }
           }
@@ -2543,8 +2772,8 @@ public class Jalview2XML
           Object[] svattrib = entry.getValue();
           int[] geom = (int[]) svattrib[0];
           String state = (String) svattrib[1];
-          Hashtable<String, Object[]> oldFiles = (Hashtable<String, Object[]>) svattrib[2];
-
+          Hashtable<File, Object[]> oldFiles = (Hashtable<File, Object[]>) svattrib[2];
+          final boolean useinJmolsuperpos = ((boolean[]) svattrib[3])[0], usetoColourbyseq = ((boolean[]) svattrib[3])[1], jmolColouring = ((boolean[]) svattrib[3])[2];
           int x = geom[0], y = geom[1], width = geom[2], height = geom[3];
           // collate the pdbfile -> sequence mappings from this view
           Vector<String> pdbfilenames = new Vector<String>();
@@ -2607,6 +2836,8 @@ public class Jalview2XML
               {
                 newFileLoc = new StringBuffer();
               }
+              do {
+                // look for next filename in load statement
               newFileLoc.append(state.substring(cp,
                       ncp = (state.indexOf("\"", ncp + 1) + 1)));
               String oldfilenam = state.substring(ncp,
@@ -2614,16 +2845,16 @@ public class Jalview2XML
               // recover the new mapping data for this old filename
               // have to normalize filename - since Jmol and jalview do filename
               // translation differently.
-              Object[] filedat = oldFiles.get(new File(oldfilenam)
-                      .toString());
-              newFileLoc.append(((String) filedat[0]));
+              Object[] filedat = oldFiles.get(new File(oldfilenam));
+              newFileLoc.append(Platform.escapeString((String) filedat[0]));
               pdbfilenames.addElement((String) filedat[0]);
               pdbids.addElement((String) filedat[1]);
-              seqmaps.addElement((SequenceI[]) ((Vector<SequenceI>) filedat[2])
+              seqmaps.addElement(((Vector<SequenceI>) filedat[2])
                       .toArray(new SequenceI[0]));
               newFileLoc.append("\"");
               cp = ecp + 1; // advance beyond last \" and set cursor so we can
                             // look for next file statement.
+              } while ((ncp=state.indexOf("/*file*/",cp))>-1);
             }
             if (cp > 0)
             {
@@ -2636,7 +2867,7 @@ public class Jalview2XML
                       .print("Ignoring incomplete Jmol state for PDB ids: ");
               newFileLoc = new StringBuffer(state);
               newFileLoc.append("; load append ");
-              for (String id : oldFiles.keySet())
+              for (File id : oldFiles.keySet())
               {
                 // add this and any other pdb files that should be present in
                 // the viewer
@@ -2645,7 +2876,7 @@ public class Jalview2XML
                 newFileLoc.append(((String) filedat[0]));
                 pdbfilenames.addElement((String) filedat[0]);
                 pdbids.addElement((String) filedat[1]);
-                seqmaps.addElement((SequenceI[]) ((Vector<SequenceI>) filedat[2])
+                seqmaps.addElement(((Vector<SequenceI>) filedat[2])
                         .toArray(new SequenceI[0]));
                 newFileLoc.append(" \"");
                 newFileLoc.append((String) filedat[0]);
@@ -2681,10 +2912,10 @@ public class Jalview2XML
               // TODO: assemble String[] { pdb files }, String[] { id for each
               // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
               // seqs_file 2}} from hash
-              final String[] pdbf = (String[]) pdbfilenames
-                      .toArray(new String[pdbfilenames.size()]), id = (String[]) pdbids
+              final String[] pdbf = pdbfilenames
+                      .toArray(new String[pdbfilenames.size()]), id = pdbids
                       .toArray(new String[pdbids.size()]);
-              final SequenceI[][] sq = (SequenceI[][]) seqmaps
+              final SequenceI[][] sq = seqmaps
                       .toArray(new SequenceI[seqmaps.size()][]);
               final String fileloc = newFileLoc.toString(), vid = sviewid;
               final AlignFrame alf = af;
@@ -2694,18 +2925,20 @@ public class Jalview2XML
               {
                 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
                 {
+                  @Override
                   public void run()
                   {
-                    AppJmol sview=null;
-                    try {
-                      sview=new AppJmol(pdbf, id, sq, alf.alignPanel, fileloc,
-                    
-                            rect, vid);
-                    }
-                    catch (OutOfMemoryError ex)
+                    AppJmol sview = null;
+                    try
+                    {
+                      sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
+                              useinJmolsuperpos, usetoColourbyseq,
+                              jmolColouring, fileloc, rect, vid);
+                    } catch (OutOfMemoryError ex)
                     {
-                      new OOMWarning("restoring structure view for PDB id "+id,(OutOfMemoryError) ex.getCause());
-                      if (sview!=null && sview.isVisible())
+                      new OOMWarning("restoring structure view for PDB id "
+                              + id, (OutOfMemoryError) ex.getCause());
+                      if (sview != null && sview.isVisible())
                       {
                         sview.closeViewer();
                         sview.setVisible(false);
@@ -2716,8 +2949,8 @@ public class Jalview2XML
                 });
               } catch (InvocationTargetException ex)
               {
-                warn("Unexpected error when opening Jmol view.",ex);
-                
+                warn("Unexpected error when opening Jmol view.", ex);
+
               } catch (InterruptedException e)
               {
                 // e.printStackTrace();
@@ -2733,18 +2966,36 @@ public class Jalview2XML
 
             // add mapping for sequences in this view to an already open Jmol
             // instance
-            for (String id : oldFiles.keySet())
+            for (File id : oldFiles.keySet())
             {
               // add this and any other pdb files that should be present in the
               // viewer
               Object[] filedat = oldFiles.get(id);
               String pdbFile = (String) filedat[0];
-              SequenceI[] seq = (SequenceI[]) ((Vector<SequenceI>) filedat[2])
+              SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
                       .toArray(new SequenceI[0]);
-              StructureSelectionManager.getStructureSelectionManager()
-                      .setMapping(seq, null, pdbFile,
-                              jalview.io.AppletFormatAdapter.FILE);
-              ((AppJmol) comp).jmb.addSequenceForStructFile(pdbFile, seq);
+              comp.jmb.ssm.setMapping(seq, null, pdbFile,
+                      jalview.io.AppletFormatAdapter.FILE);
+              comp.jmb.addSequenceForStructFile(pdbFile, seq);
+            }
+            // and add the AlignmentPanel's reference to the Jmol view
+            comp.addAlignmentPanel(ap);
+            if (useinJmolsuperpos)
+            {
+              comp.useAlignmentPanelForSuperposition(ap);
+            }
+            else
+            {
+              comp.excludeAlignmentPanelForSuperposition(ap);
+            }
+            if (usetoColourbyseq)
+            {
+              comp.useAlignmentPanelForColourbyseq(ap,
+                      !jmolColouring);
+            }
+            else
+            {
+              comp.excludeAlignmentPanelForColourbyseq(ap);
             }
           }
         }
@@ -2755,9 +3006,9 @@ public class Jalview2XML
   }
 
   AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
-          Alignment al, boolean hideConsensus, boolean hideQuality,
-          boolean hideConservation, JalviewModelSequence jms,
-          Viewport view, String uniqueSeqSetId, String viewId)
+          Alignment al, JalviewModelSequence jms, Viewport view,
+          String uniqueSeqSetId, String viewId,
+          ArrayList<JvAnnotRow> autoAlan)
   {
     AlignFrame af = null;
     af = new AlignFrame(al, view.getWidth(), view.getHeight(),
@@ -2767,7 +3018,7 @@ public class Jalview2XML
 
     for (int i = 0; i < JSEQ.length; i++)
     {
-      af.viewport.setSequenceColour(af.viewport.alignment.getSequenceAt(i),
+      af.viewport.setSequenceColour(af.viewport.getAlignment().getSequenceAt(i),
               new java.awt.Color(JSEQ[i].getColour()));
     }
 
@@ -2778,7 +3029,7 @@ public class Jalview2XML
       jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
               .get(uniqueSeqSetId);
 
-      af.viewport.sequenceSetID = uniqueSeqSetId;
+      af.viewport.setSequenceSetId(uniqueSeqSetId);
       if (av != null)
       {
         // propagate shared settings to this new view
@@ -2819,27 +3070,6 @@ public class Jalview2XML
       af.viewport.hideSequence(hseqs);
 
     }
-    // set visibility of annotation in view
-    if ((hideConsensus || hideQuality || hideConservation)
-            && al.getAlignmentAnnotation() != null)
-    {
-      int hSize = al.getAlignmentAnnotation().length;
-      for (int h = 0; h < hSize; h++)
-      {
-        if ((hideConsensus && al.getAlignmentAnnotation()[h].label
-                .equals("Consensus"))
-                || (hideQuality && al.getAlignmentAnnotation()[h].label
-                        .equals("Quality"))
-                || (hideConservation && al.getAlignmentAnnotation()[h].label
-                        .equals("Conservation")))
-        {
-          al.deleteAnnotation(al.getAlignmentAnnotation()[h]);
-          hSize--;
-          h--;
-        }
-      }
-      af.alignPanel.adjustAnnotationHeight();
-    }
     // recover view properties and display parameters
     if (view.getViewName() != null)
     {
@@ -2889,18 +3119,18 @@ public class Jalview2XML
       else if (view.getBgColour().startsWith("Annotation"))
       {
         // int find annotation
-        if (af.viewport.alignment.getAlignmentAnnotation() != null)
+        if (af.viewport.getAlignment().getAlignmentAnnotation() != null)
         {
-          for (int i = 0; i < af.viewport.alignment
+          for (int i = 0; i < af.viewport.getAlignment()
                   .getAlignmentAnnotation().length; i++)
           {
-            if (af.viewport.alignment.getAlignmentAnnotation()[i].label
+            if (af.viewport.getAlignment().getAlignmentAnnotation()[i].label
                     .equals(view.getAnnotationColours().getAnnotation()))
             {
-              if (af.viewport.alignment.getAlignmentAnnotation()[i]
+              if (af.viewport.getAlignment().getAlignmentAnnotation()[i]
                       .getThreshold() == null)
               {
-                af.viewport.alignment.getAlignmentAnnotation()[i]
+                af.viewport.getAlignment().getAlignmentAnnotation()[i]
                         .setThreshold(new jalview.datamodel.GraphLine(view
                                 .getAnnotationColours().getThreshold(),
                                 "Threshold", java.awt.Color.black)
@@ -2912,7 +3142,7 @@ public class Jalview2XML
                       .equals("None"))
               {
                 cs = new AnnotationColourGradient(
-                        af.viewport.alignment.getAlignmentAnnotation()[i],
+                        af.viewport.getAlignment().getAlignmentAnnotation()[i],
                         new java.awt.Color(view.getAnnotationColours()
                                 .getMinColour()), new java.awt.Color(view
                                 .getAnnotationColours().getMaxColour()),
@@ -2922,7 +3152,7 @@ public class Jalview2XML
                       .startsWith("ucs"))
               {
                 cs = new AnnotationColourGradient(
-                        af.viewport.alignment.getAlignmentAnnotation()[i],
+                        af.viewport.getAlignment().getAlignmentAnnotation()[i],
                         GetUserColourScheme(jms, view
                                 .getAnnotationColours().getColourScheme()),
                         view.getAnnotationColours().getAboveThreshold());
@@ -2930,7 +3160,7 @@ public class Jalview2XML
               else
               {
                 cs = new AnnotationColourGradient(
-                        af.viewport.alignment.getAlignmentAnnotation()[i],
+                        af.viewport.getAlignment().getAlignmentAnnotation()[i],
                         ColourSchemeProperty.getColour(al, view
                                 .getAnnotationColours().getColourScheme()),
                         view.getAnnotationColours().getAboveThreshold());
@@ -2941,8 +3171,8 @@ public class Jalview2XML
               {
                 for (int g = 0; g < al.getGroups().size(); g++)
                 {
-                  jalview.datamodel.SequenceGroup sg = (jalview.datamodel.SequenceGroup) al
-                          .getGroups().elementAt(g);
+                  jalview.datamodel.SequenceGroup sg = al
+                          .getGroups().get(g);
 
                   if (sg.cs == null)
                   {
@@ -2953,7 +3183,7 @@ public class Jalview2XML
                    * if
                    * (view.getAnnotationColours().getColourScheme().equals("None"
                    * )) { sg.cs = new AnnotationColourGradient(
-                   * af.viewport.alignment.getAlignmentAnnotation()[i], new
+                   * af.viewport.getAlignment().getAlignmentAnnotation()[i], new
                    * java.awt.Color(view.getAnnotationColours().
                    * getMinColour()), new
                    * java.awt.Color(view.getAnnotationColours().
@@ -2962,7 +3192,7 @@ public class Jalview2XML
                    */
                   {
                     sg.cs = new AnnotationColourGradient(
-                            af.viewport.alignment.getAlignmentAnnotation()[i],
+                            af.viewport.getAlignment().getAlignmentAnnotation()[i],
                             sg.cs, view.getAnnotationColours()
                                     .getAboveThreshold());
                   }
@@ -2984,7 +3214,7 @@ public class Jalview2XML
       if (cs != null)
       {
         cs.setThreshold(view.getPidThreshold(), true);
-        cs.setConsensus(af.viewport.hconsensus);
+        cs.setConsensus(af.viewport.getSequenceConsensusHash());
       }
     }
 
@@ -3010,8 +3240,8 @@ public class Jalview2XML
     }
     if (view.hasIgnoreGapsinConsensus())
     {
-      af.viewport.ignoreGapsInConsensusCalculation = view
-              .getIgnoreGapsinConsensus();
+      af.viewport.setIgnoreGapsConsensus(view
+              .getIgnoreGapsinConsensus(), null);
     }
     if (view.hasFollowHighlight())
     {
@@ -3032,11 +3262,11 @@ public class Jalview2XML
     }
     if (view.hasShowSequenceLogo())
     {
-      af.viewport.showSequenceLogo = view.getShowSequenceLogo();
+      af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
     }
     else
     {
-      af.viewport.showSequenceLogo = false;
+      af.viewport.setShowSequenceLogo(false);
     }
     if (view.hasShowDbRefTooltip())
     {
@@ -3137,20 +3367,112 @@ public class Jalview2XML
                 );
       }
     }
-
+    if (view.getCalcIdParam()!=null)
+    {
+      for (CalcIdParam calcIdParam:view.getCalcIdParam())
+      {
+        if (recoverCalcIdParam(calcIdParam, af.viewport)) {
+        } else {
+          warn("Couldn't recover parameters for "+calcIdParam.getCalcId());
+        }
+      }
+    }
     af.setMenusFromViewport(af.viewport);
     // 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
+    reorderAutoannotation(af, al, autoAlan);
     return af;
   }
 
+  private void reorderAutoannotation(AlignFrame af, Alignment al,
+          ArrayList<JvAnnotRow> autoAlan)
+  {
+    // copy over visualization settings for autocalculated annotation in the
+    // view
+    if (al.getAlignmentAnnotation() != null)
+    {
+      /**
+       * Kludge for magic autoannotation names (see JAL-811)
+       */
+      String[] magicNames = new String[]
+      { "Consensus", "Quality", "Conservation" };
+      JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
+      Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
+      for (String nm : magicNames)
+      {
+        visan.put(nm, nullAnnot);
+      }
+      for (JvAnnotRow auan : autoAlan)
+      {
+        visan.put(auan.template.label+(auan.template.getCalcId()==null ? "" : "\t"+auan.template.getCalcId()), auan);
+      }
+      int hSize = al.getAlignmentAnnotation().length;
+      ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
+      // work through any autoCalculated annotation already on the view
+      // removing it if it should be placed in a different location on the
+      // annotation panel.
+      for (int h = 0; h < hSize; h++)
+      {
+        jalview.datamodel.AlignmentAnnotation jalan = al
+                .getAlignmentAnnotation()[h];
+        if (jalan.autoCalculated)
+        {
+          JvAnnotRow valan = visan.get(jalan.label);
+          if (jalan.getCalcId()!=null)
+          {
+            valan = visan.get(jalan.label+ "\t"+jalan.getCalcId());
+          }
+          
+          if (valan != null)
+          {
+            // delete the auto calculated row from the alignment
+            al.deleteAnnotation(jalan, false);
+            hSize--;
+            h--;
+            if (valan != nullAnnot)
+            {
+              if (jalan != valan.template)
+              {
+                // newly created autoannotation row instance
+                // so keep a reference to the visible annotation row
+                // and copy over all relevant attributes
+                if (valan.template.graphHeight >= 0)
+
+                {
+                  jalan.graphHeight = valan.template.graphHeight;
+                }
+                jalan.visible = valan.template.visible;
+              }
+              reorder.add(new JvAnnotRow(valan.order, jalan));
+            }
+          }
+        }
+      }
+      int s = 0, srt[] = new int[reorder.size()];
+      JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
+      for (JvAnnotRow jvar : reorder)
+      {
+        rws[s] = jvar;
+        srt[s++] = jvar.order;
+      }
+      reorder.clear();
+      jalview.util.QuickSort.sort(srt, rws);
+      // and re-insert the annotation at its correct position
+      for (JvAnnotRow jvar : rws)
+      {
+        al.addAnnotation(jvar.template, jvar.order);
+      }
+      af.alignPanel.adjustAnnotationHeight();
+    }
+  }
+
   Hashtable skipList = null;
 
   /**
    * TODO remove this method
-   * 
+   *
    * @param view
    * @return AlignFrame bound to sequenceSetId from view, if one exists. private
    *         AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
@@ -3161,7 +3483,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
    */
@@ -3234,7 +3556,7 @@ public class Jalview2XML
   }
 
   /**
-   * 
+   *
    * @param vamsasSeq
    *          sequence definition to create/merge dataset sequence for
    * @param ds
@@ -3252,7 +3574,7 @@ public class Jalview2XML
     jalview.datamodel.SequenceI dsq = null;
     if (sq != null && sq.getDatasetSequence() != null)
     {
-      dsq = (jalview.datamodel.SequenceI) sq.getDatasetSequence();
+      dsq = sq.getDatasetSequence();
     }
 
     String sqid = vamsasSeq.getDsseqid();
@@ -3358,7 +3680,7 @@ public class Jalview2XML
 
   /**
    * make a new dataset ID for this jalview dataset alignment
-   * 
+   *
    * @param dataset
    * @return
    */
@@ -3525,11 +3847,11 @@ public class Jalview2XML
     af.closeMenuItem_actionPerformed(true);
 
     /*
-     * if(ap.av.alignment.getAlignmentAnnotation()!=null) { for(int i=0;
-     * i<ap.av.alignment.getAlignmentAnnotation().length; i++) {
-     * if(!ap.av.alignment.getAlignmentAnnotation()[i].autoCalculated) {
-     * af.alignPanel.av.alignment.getAlignmentAnnotation()[i] =
-     * ap.av.alignment.getAlignmentAnnotation()[i]; } } }
+     * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
+     * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
+     * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
+     * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
+     * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
      */
 
     return af.alignPanel;
@@ -3539,15 +3861,16 @@ public class Jalview2XML
    * flag indicating if hashtables should be cleared on finalization TODO this
    * flag may not be necessary
    */
-  private boolean _cleartables = true;
+  private final boolean _cleartables = true;
 
   private Hashtable jvids2vobj;
 
   /*
    * (non-Javadoc)
-   * 
+   *
    * @see java.lang.Object#finalize()
    */
+  @Override
   protected void finalize() throws Throwable
   {
     // really make sure we have no buried refs left.
@@ -3622,13 +3945,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)
@@ -3700,7 +4023,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)
@@ -3712,7 +4035,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)