save and recover graph height, visibility and row position for autocalculated annotat...
authorjprocter <Jim Procter>
Thu, 21 Apr 2011 13:19:38 +0000 (13:19 +0000)
committerjprocter <Jim Procter>
Thu, 21 Apr 2011 13:19:38 +0000 (13:19 +0000)
src/jalview/gui/Jalview2XML.java

index 1fe6bf4..147a68d 100755 (executable)
@@ -32,6 +32,7 @@ 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.*;
@@ -834,19 +835,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);
+        
         if (aa[i].graph > 0)
         {
           an.setGraph(true);
@@ -867,6 +862,13 @@ public class Jalview2XML
         }
 
         an.setLabel(aa[i].label);
+
+        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);
+        }
         if (aa[i].hasScore())
         {
           an.setScore(aa[i].getScore());
@@ -904,6 +906,11 @@ 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
@@ -1825,6 +1832,25 @@ 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
    * 
@@ -2057,11 +2083,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)
     {
@@ -2069,22 +2095,27 @@ 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"))
-        {
-          hideConsensus = false;
-          continue;
+        if (autoForView  || (an[i].hasAutoCalculated() && an[i].isAutoCalculated())) {
+          // 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()))
@@ -2107,7 +2138,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)
@@ -2137,8 +2167,12 @@ 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();
 
@@ -2150,33 +2184,45 @@ 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())
@@ -2200,7 +2246,19 @@ 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 (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);
+        }
       }
     }
 
@@ -2289,11 +2347,24 @@ 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);
@@ -2371,9 +2442,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,14 +2570,10 @@ public class Jalview2XML
               if (!jmolViewIds.containsKey(sviewid))
               {
                 jmolViewIds.put(sviewid, new Object[]
-                {
-                    new int[]
-                    { x, y, width, height },
-                    "",
-                    new Hashtable<String, Object[]>(),
-                    new boolean[]
-                    {
-                        false,false} });
+                { new int[]
+                { x, y, width, height }, "",
+                    new Hashtable<String, Object[]>(), new boolean[]
+                    { false, false } });
                 // Legacy->2.7 conversion: if there is no attribute for
                 // colouring with the alignPanel then by default we set the
                 // first encountered view to be the default source of colour
@@ -2721,8 +2787,7 @@ public class Jalview2XML
                     try
                     {
                       sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
-                              useinJmolsuperpos, usetoColourbyseq,
-                              fileloc,
+                              useinJmolsuperpos, usetoColourbyseq, fileloc,
                               rect, vid);
                     } catch (OutOfMemoryError ex)
                     {
@@ -2796,9 +2861,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(),
@@ -2860,27 +2925,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)
     {
@@ -3184,9 +3228,82 @@ public class Jalview2XML
     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);
+      }
+      int hSize = al.getAlignmentAnnotation().length;
+      ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
+      for (int h = 0; h < hSize; h++)
+      {
+        jalview.datamodel.AlignmentAnnotation jalan = al
+                .getAlignmentAnnotation()[h];
+        if (jalan.autoCalculated)
+        {
+          JvAnnotRow valan = visan.get(jalan.label);
+          if (valan != null)
+          {
+            // delete the auto calculated row from the alignment
+            al.deleteAnnotation(al.getAlignmentAnnotation()[h],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;
 
   /**