Annotations move when full alignment edited
[jalview.git] / src / jalview / gui / Jalview2XML.java
index f188e31..0cac9c1 100755 (executable)
@@ -21,8 +21,6 @@ package jalview.gui;
 
 import jalview.schemes.*;
 
-import jalview.gui.*;
-
 import java.io.*;
 
 import java.net.*;
@@ -48,6 +46,21 @@ import jalview.schemabinding.version2.*;
  */
 public class Jalview2XML
 {
+
+  Hashtable seqRefIds;
+
+  /**
+   * This maintains a list of viewports, the key being the
+   * seqSetId. Important to set historyItem and redoList
+   * for multiple views
+   */
+  Hashtable viewportsAdded;
+
+  Hashtable annotationIds = new Hashtable();
+
+  String uniqueSetSuffix = "";
+
+
     // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
     public void SaveState(File statefile)
     {
@@ -112,9 +125,6 @@ public class Jalview2XML
                       AlignmentPanel apanel = (AlignmentPanel) af.alignPanels.
                           elementAt(ap);
 
-                      if (apanel.av.explodedPosition == null)
-                        apanel.av.explodedPosition = af.getBounds();
-
                       SaveState(apanel,
                                 apSize == 1 ? shortName : ap+shortName,
                                 jout, out);
@@ -132,7 +142,7 @@ public class Jalview2XML
     }
 
     // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
-    public void SaveAlignment(AlignFrame af, String jarFile,
+    public boolean SaveAlignment(AlignFrame af, String jarFile,
         String fileName)
     {
         try
@@ -146,9 +156,6 @@ public class Jalview2XML
           {
             AlignmentPanel apanel = (AlignmentPanel)af.alignPanels.elementAt(ap);
 
-            if (apanel.av.explodedPosition == null)
-              apanel.av.explodedPosition = af.getBounds();
-
             SaveState(apanel,
                       apSize==1?fileName:fileName+ap,
                       jout, out);
@@ -156,10 +163,12 @@ public class Jalview2XML
 
           out.close();
           jout.close();
+          return true;
         }
         catch (Exception ex)
         {
           ex.printStackTrace();
+          return false;
         }
     }
 
@@ -172,7 +181,7 @@ public class Jalview2XML
      * @param jout DOCUMENT ME!
      * @param out DOCUMENT ME!
      */
-    public void SaveState(AlignmentPanel ap,
+    public JalviewModel SaveState(AlignmentPanel ap,
                           String fileName,
                           JarOutputStream jout,
                           PrintWriter out)
@@ -208,9 +217,11 @@ public class Jalview2XML
 
         //SAVE SEQUENCES
         int id = 0;
+        jalview.datamodel.SequenceI jds;
         for (int i = 0; i < jal.getHeight(); i++)
         {
-            id = jal.getSequenceAt(i).hashCode();
+            jds = jal.getSequenceAt(i);
+            id = jds.hashCode();
 
             if(seqRefIds.get(id+"")!=null)
             {
@@ -220,14 +231,14 @@ public class Jalview2XML
             {
               vamsasSeq = new Sequence();
               vamsasSeq.setId(id + "");
-              vamsasSeq.setName(jal.getSequenceAt(i).getName());
-              vamsasSeq.setSequence(jal.getSequenceAt(i).getSequence());
-              vamsasSeq.setDescription(jal.getSequenceAt(i).getDescription());
+              vamsasSeq.setName(jds.getName());
+              vamsasSeq.setSequence(jds.getSequenceAsString());
+              vamsasSeq.setDescription(jds.getDescription());
 
-              if (jal.getSequenceAt(i).getDatasetSequence().getDBRef() != null)
+              if (jds.getDatasetSequence().getDBRef() != null)
               {
                 jalview.datamodel.DBRefEntry[] dbrefs =
-                    jal.getSequenceAt(i).getDatasetSequence().getDBRef();
+                    jds.getDatasetSequence().getDBRef();
 
                 for (int d = 0; d < dbrefs.length; d++)
                 {
@@ -240,40 +251,43 @@ public class Jalview2XML
               }
 
               vamsasSet.addSequence(vamsasSeq);
-              seqRefIds.put(id+"", vamsasSeq);
+              seqRefIds.put(id+"", jal.getSequenceAt(i));
             }
 
             jseq = new JSeq();
-            jseq.setStart(jal.getSequenceAt(i).getStart());
-            jseq.setEnd(jal.getSequenceAt(i).getEnd());
-            jseq.setColour(jal.getSequenceAt(i).getColor().getRGB());
+            jseq.setStart(jds.getStart());
+            jseq.setEnd(jds.getEnd());
+            jseq.setColour( av.getSequenceColour(jds).getRGB());
 
             jseq.setId(id);
 
             if (av.hasHiddenRows)
             {
-              jseq.setHidden(av.alignment.getHiddenSequences().isHidden(
-                  jal.getSequenceAt(i)));
+              jseq.setHidden(av.alignment.getHiddenSequences().isHidden(jds));
 
-              if(jal.getSequenceAt(i).getHiddenSequences()!=null)
+              if(av.hiddenRepSequences!=null
+              && av.hiddenRepSequences.containsKey(jal.getSequenceAt(i)))
               {
-                jalview.datamodel.SequenceI [] reps =
-                    jal.getSequenceAt(i).getHiddenSequences().getSequencesInOrder(jal);
+                jalview.datamodel.SequenceI[] reps =
+                    ( (jalview.datamodel.SequenceGroup)
+                     av.hiddenRepSequences.get(
+                         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(jal.getSequenceAt(i).getDatasetSequence().getSequenceFeatures()!=null)
+            if(jds.getDatasetSequence().getSequenceFeatures()!=null)
             {
               jalview.datamodel.SequenceFeature[] sf
-                  = jal.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
+                  = jds.getDatasetSequence().getSequenceFeatures();
               int index = 0;
               while(index < sf.length)
               {
@@ -315,9 +329,9 @@ public class Jalview2XML
               }
             }
 
-            if(jal.getSequenceAt(i).getDatasetSequence().getPDBId()!=null)
+            if(jds.getDatasetSequence().getPDBId()!=null)
             {
-              Enumeration en = jal.getSequenceAt(i).getDatasetSequence().getPDBId().elements();
+              Enumeration en = jds.getDatasetSequence().getPDBId().elements();
               while(en.hasMoreElements())
               {
                 Pdbids pdb = new Pdbids();
@@ -327,19 +341,20 @@ public class Jalview2XML
                 pdb.setId(entry.getId());
                 pdb.setType(entry.getType());
 
+
                 if(entry.getFile()!=null)
                 {
+                  pdb.setFile(entry.getFile());
                   if(pdbfiles==null)
                     pdbfiles = new Vector();
 
-
                   if(!pdbfiles.contains(entry.getId()))
                   {
                     pdbfiles.addElement(entry.getId());
                     try
                     {
                       File file = new File(entry.getFile());
-                      if(file.exists())
+                      if(file.exists() && jout!=null)
                       {
                         byte[] data = new byte[ (int) file.length()];
                         jout.putNextEntry(new JarEntry(entry.getId()));
@@ -441,6 +456,13 @@ public class Jalview2XML
             {
                 Annotation an = new Annotation();
 
+                if(aa[i].annotationId!=null)
+                {
+                  annotationIds.put(aa[i].annotationId, aa[i]);
+                }
+
+                an.setId(aa[i].annotationId);
+
                 if (aa[i].label.equals("Quality") ||
                         aa[i].label.equals("Conservation") ||
                         aa[i].label.equals("Consensus"))
@@ -561,8 +583,11 @@ public class Jalview2XML
                 groups[i].setDisplayBoxes(sg.getDisplayBoxes());
                 groups[i].setDisplayText(sg.getDisplayText());
                 groups[i].setColourText(sg.getColourText());
+                groups[i].setTextCol1(sg.textColour.getRGB());
+                groups[i].setTextCol2(sg.textColour2.getRGB());
+                groups[i].setTextColThreshold(sg.thresholdTextColour);
 
-                for (int s = 0; s < sg.getSize(false); s++)
+                for (int s = 0; s < sg.getSize(); s++)
                 {
                     jalview.datamodel.Sequence seq =
                         (jalview.datamodel.Sequence) sg.getSequenceAt(s);
@@ -581,10 +606,22 @@ public class Jalview2XML
         view.setViewName(av.viewName);
         view.setGatheredViews(av.gatherViewsHere);
 
-        view.setXpos(av.explodedPosition.x);
-        view.setYpos(av.explodedPosition.y);
-        view.setWidth(av.explodedPosition.width);
-        view.setHeight(av.explodedPosition.height);
+
+        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);
 
@@ -646,9 +683,14 @@ public class Jalview2XML
         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.setWrapAlignment(av.getWrapAlignment());
+        view.setTextCol1(av.textColour.getRGB());
+        view.setTextCol2(av.textColour2.getRGB());
+        view.setTextColThreshold(av.thresholdTextColour);
+
 
         if(av.featuresDisplayed!=null)
         {
@@ -718,22 +760,29 @@ public class Jalview2XML
         object.setJalviewModelSequence(jms);
         object.getVamsasModel().addSequenceSet(vamsasSet);
 
-        try
+        if(out!=null)
         {
+          //We may not want to right the object to disk,
+          //eg we can copy the alignViewport to a new view object
+          //using save and then load
+          try
+          {
             if (!fileName.endsWith(".xml"))
             {
-                fileName = fileName + ".xml";
+              fileName = fileName + ".xml";
             }
 
             JarEntry entry = new JarEntry(fileName);
             jout.putNextEntry(entry);
 
             object.marshal(out);
-        }
-        catch (Exception ex)
-        {
+          }
+          catch (Exception ex)
+          {
             ex.printStackTrace();
+          }
         }
+        return object;
     }
 
     String SetUserColourScheme(jalview.schemes.ColourSchemeI cs,
@@ -819,14 +868,6 @@ public class Jalview2XML
         return ucs;
     }
 
-    Hashtable seqRefIds;
-
-    /**
-     * This maintains a list of viewports, the key being the
-     * seqSetId. Important to set historyItem and redoList
-     * for multiple views
-     */
-    Hashtable viewportsAdded;
 
     /**
      * DOCUMENT ME!
@@ -835,6 +876,8 @@ public class Jalview2XML
      */
     public AlignFrame LoadJalviewAlign(final String file)
     {
+        uniqueSetSuffix = System.currentTimeMillis()%100000 +"";
+
         jalview.gui.AlignFrame af = null;
 
         seqRefIds = new Hashtable();
@@ -881,7 +924,7 @@ public class Jalview2XML
                     unmar.setValidation(false);
                     object = (JalviewModel) unmar.unmarshal( in );
 
-                    af = LoadFromObject(object, file);
+                    af = LoadFromObject(object, file, true);
                     if(af.viewport.gatherViewsHere)
                     {
                       gatherToThisFrame.add(af);
@@ -923,6 +966,7 @@ public class Jalview2XML
             System.out.println("Successfully loaded archive file");
             return af;
           }
+          ex.printStackTrace();
 
             System.err.println("Exception whilst loading jalview XML file : " +
                 ex + "\n");
@@ -952,6 +996,7 @@ public class Jalview2XML
 
     String loadPDBFile(String file, String pdbId)
     {
+      System.out.println(file +" "+pdbId);
       try
       {
         JarInputStream jin = null;
@@ -995,7 +1040,9 @@ public class Jalview2XML
     }
 
 
-    AlignFrame LoadFromObject(JalviewModel object, String file)
+    AlignFrame LoadFromObject(JalviewModel object,
+                              String file,
+                              boolean loadTrees )
     {
         SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
         Sequence[] vamsasSeq = vamsasSet.getSequence();
@@ -1012,7 +1059,6 @@ public class Jalview2XML
 
         ArrayList tmpseqs = new ArrayList();
 
-
         boolean multipleView = false;
 
         JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
@@ -1032,12 +1078,12 @@ public class Jalview2XML
             jseq.setDescription(vamsasSeq[i].getDescription());
             jseq.setStart(JSEQ[i].getStart());
             jseq.setEnd(JSEQ[i].getEnd());
-            jseq.setColor(new java.awt.Color(JSEQ[i].getColour()));
             seqRefIds.put(vamsasSeq[i].getId(), jseq);
             tmpseqs.add( jseq );
           }
 
 
+
           if (JSEQ[i].getHidden())
           {
             if (hiddenSeqs == null)
@@ -1169,10 +1215,20 @@ public class Jalview2XML
                  continue;
                }
 
+               if (an[i].getId() != null
+                   && annotationIds.containsKey(an[i].getId()))
+               {
+                 al.addAnnotation(
+                     (jalview.datamodel.AlignmentAnnotation)annotationIds.get(an[i].getId())
+                     );
+
+                 continue;
+              }
+
                 AnnotationElement[] ae = an[i].getAnnotationElement();
                 jalview.datamodel.Annotation[] anot = new jalview.datamodel.Annotation[al.getWidth()];
 
-                for (int aa = 0; aa < ae.length; aa++)
+                for (int aa = 0; aa < ae.length && aa<anot.length; aa++)
                 {
                     anot[ae[aa].getPosition()] = new jalview.datamodel.Annotation(ae[aa].getDisplayCharacter(),
                             ae[aa].getDescription(),
@@ -1208,6 +1264,12 @@ public class Jalview2XML
                             an[i].getDescription(), anot);
                 }
 
+                if(an[i].getId()!=null)
+                {
+                  annotationIds.put(an[i].getId(), jaa);
+                  jaa.annotationId = an[i].getId();
+                }
+
                 if(an[i].getSequenceRef()!=null)
                 {
                   jaa.createSequenceMapping(
@@ -1262,10 +1324,14 @@ public class Jalview2XML
                 sg.setOutlineColour(new java.awt.Color(
                         groups[i].getOutlineColour()));
 
+                sg.textColour = new java.awt.Color(groups[i].getTextCol1());
+                sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
+                sg.thresholdTextColour = groups[i].getTextColThreshold();
+
                 if (groups[i].getConsThreshold() != 0)
                 {
                     jalview.analysis.Conservation c = new jalview.analysis.Conservation("All",
-                            ResidueProperties.propHash, 3, sg.getSequences(false), 0,
+                            ResidueProperties.propHash, 3, sg.getSequences(null), 0,
                             sg.getWidth() - 1);
                     c.calculate();
                     c.verdict(false, 25);
@@ -1284,7 +1350,21 @@ public class Jalview2XML
                                        view.getWidth(),
                                        view.getHeight() );
 
-        af.viewport.sequenceSetID = view.getSequenceSetId();
+        af.setFileName(file, "Jalview");
+
+        for (int i = 0; i < JSEQ.length; i++)
+        {
+          af.viewport.setSequenceColour(
+              af.viewport.alignment.getSequenceAt(i),
+              new java.awt.Color(
+                  JSEQ[i].getColour()));
+        }
+
+        //If we just load in the same jar file again, the sequenceSetId
+        //will be the same, and we end up with multiple references
+        //to the same sequenceSet. We must modify this id on load
+        //so that each load of the file gives a unique id
+        String uniqueSeqSetId =  view.getSequenceSetId()+uniqueSetSuffix;
 
         af.viewport.gatherViewsHere = view.getGatheredViews();
 
@@ -1292,30 +1372,37 @@ public class Jalview2XML
         {
           jalview.gui.AlignViewport av =
               (jalview.gui.AlignViewport)
-              viewportsAdded.get(view.getSequenceSetId());
+              viewportsAdded.get(uniqueSeqSetId);
 
+          af.viewport.sequenceSetID = uniqueSeqSetId;
           if(av!=null)
           {
+
             af.viewport.historyList = av.historyList;
             af.viewport.redoList = av.redoList;
           }
           else
           {
-            viewportsAdded.put(view.getSequenceSetId(), af.viewport);
+            viewportsAdded.put(uniqueSeqSetId, af.viewport);
           }
 
-          PaintRefresher.Register(af.alignPanel, view.getSequenceSetId());
+          PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
         }
         if(hiddenSeqs!=null)
         {
           for(int s=0; s<JSEQ.length; s++)
           {
+            jalview.datamodel.SequenceGroup hidden =
+                new jalview.datamodel.SequenceGroup();
+
             for(int r=0; r<JSEQ[s].getHiddenSequencesCount(); r++)
             {
-              al.getSequenceAt(s).addHiddenSequence(
-                  al.getSequenceAt( JSEQ[s].getHiddenSequences(r)  )
+              hidden.addSequence(
+                  al.getSequenceAt(JSEQ[s].getHiddenSequences(r))
+                  , false
                   );
             }
+            af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
           }
 
           jalview.datamodel.SequenceI [] hseqs = new
@@ -1353,11 +1440,14 @@ public class Jalview2XML
           af.alignPanel.adjustAnnotationHeight();
         }
 
-        af.viewport.viewName = view.getViewName();
+        if(view.getViewName()!=null)
+        {
+          af.viewport.viewName = view.getViewName();
+          af.setInitialTabVisible();
+        }
         af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
             view.getHeight());
-        af.viewport.setStartRes(view.getStartRes());
-        af.viewport.setStartSeq(view.getStartSeq());
+
         af.viewport.setShowAnnotation(view.getShowAnnotation());
         af.viewport.setAbovePIDThreshold(view.getPidSelected());
 
@@ -1365,6 +1455,7 @@ public class Jalview2XML
 
         af.viewport.setConservationSelected(view.getConservationSelected());
         af.viewport.setShowJVSuffix(view.getShowFullId());
+        af.viewport.rightAlignIds=view.getRightAlignIds();
         af.viewport.setFont(new java.awt.Font(view.getFontName(),
                 view.getFontStyle(), view.getFontSize()));
         af.alignPanel.fontChanged();
@@ -1378,6 +1469,12 @@ public class Jalview2XML
 
         af.viewport.setShowText(view.getShowText());
 
+        af.viewport.textColour = new java.awt.Color(view.getTextCol1());
+        af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
+        af.viewport.thresholdTextColour = view.getTextColThreshold();
+
+        af.viewport.setStartRes(view.getStartRes());
+        af.viewport.setStartSeq(view.getStartSeq());
 
         ColourSchemeI cs = null;
 
@@ -1548,7 +1645,7 @@ public class Jalview2XML
 
         //LOAD TREES
         ///////////////////////////////////////
-        if (jms.getTreeCount() > 0)
+        if (loadTrees && jms.getTreeCount() > 0)
         {
             try
             {
@@ -1594,5 +1691,39 @@ public class Jalview2XML
 
         return af;
     }
+
+    public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap, boolean keepSeqRefs )
+    {
+      jalview.schemabinding.version2.JalviewModel jm
+          = SaveState(ap, null, null, null);
+
+      if (!keepSeqRefs)
+      {
+        seqRefIds.clear();
+        jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
+      }
+      else
+        uniqueSetSuffix = "";
+
+      viewportsAdded = new Hashtable();
+
+      AlignFrame af = LoadFromObject(jm, null, false);
+      af.alignPanels.clear();
+      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];
+          }
+        }
+      }   */
+
+      return af.alignPanel;
+    }
 }