JAL-1177 new flag to write a dataset only jalview XML document
authorJim Procter <jprocter@dundee.ac.uk>
Fri, 25 Apr 2014 13:24:56 +0000 (14:24 +0100)
committerJim Procter <jprocter@dundee.ac.uk>
Fri, 25 Apr 2014 13:24:56 +0000 (14:24 +0100)
src/jalview/gui/Jalview2XML.java

index ce42174..5f9a131 100644 (file)
@@ -420,6 +420,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();
@@ -449,6 +469,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)
     {
@@ -468,10 +493,11 @@ public class Jalview2XML
 
     // 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 +529,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 +598,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 +609,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 +679,7 @@ public class Jalview2XML
                     }
                     pdb.addStructureState(state);
                   }
+
                 }
               }
             }
@@ -713,7 +748,7 @@ public class Jalview2XML
       jms.addJSeq(jseq);
     }
 
-    if (av.hasHiddenRows())
+    if (!storeDS && av.hasHiddenRows())
     {
       jal = av.getAlignment();
     }
@@ -757,7 +792,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 +839,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
@@ -1015,253 +937,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());
-      ac.setPerSequence(acg.isSeqAssociated());
-      ac.setPredefinedColours(acg.isPredefinedColours());
-      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.setConsThreshold(cs.getConservationInc());
+          if (cs instanceof jalview.schemes.UserColourScheme)
+          {
+            view.setBgColour(SetUserColourScheme(cs, userColours, jms));
+          }
+        }
+
+        if (cs instanceof ResidueColourScheme)
         {
-          view.setBgColour(SetUserColourScheme(cs, userColours, jms));
+          view.setPidThreshold(cs.getThreshold());
         }
       }
 
-      if (cs instanceof ResidueColourScheme)
+      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)
       {
-        view.setPidThreshold(cs.getThreshold());
-      }
-    }
+        jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
+
+        String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
 
-    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;
-
-      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)
+          for (int ro = 0; ro < renderOrder.length; ro++)
           {
-            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());
+            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);
 
@@ -1290,6 +1214,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);