JAL-3070 pull up generic methods for an automatic alignment analysis web service...
[jalview.git] / src / jalview / project / Jalview2XML.java
index 0e17779..d5f6a5d 100644 (file)
@@ -41,6 +41,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.GeneLocus;
 import jalview.datamodel.GraphLine;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Point;
 import jalview.datamodel.RnaViewerModel;
@@ -60,7 +61,6 @@ import jalview.gui.AlignmentPanel;
 import jalview.gui.AppVarna;
 import jalview.gui.ChimeraViewFrame;
 import jalview.gui.Desktop;
-import jalview.gui.FeatureRenderer;
 import jalview.gui.JvOptionPane;
 import jalview.gui.OOMWarning;
 import jalview.gui.PCAPanel;
@@ -73,6 +73,7 @@ import jalview.gui.TreePanel;
 import jalview.io.BackupFiles;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
+import jalview.io.HMMFile;
 import jalview.io.NewickFile;
 import jalview.math.Matrix;
 import jalview.math.MatrixI;
@@ -94,6 +95,7 @@ import jalview.util.matcher.Condition;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.PCAModel;
 import jalview.viewmodel.ViewportRanges;
+import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
 import jalview.ws.jws2.Jws2Discoverer;
@@ -214,6 +216,8 @@ public class Jalview2XML
 
   private static final String RNA_PREFIX = "rna_";
 
+  private static final String HMMER_PREFIX = "hmmer_";
+
   private static final String UTF_8 = "UTF-8";
 
   /**
@@ -1052,6 +1056,9 @@ public class Jalview2XML
         jseq.getFeatures().add(features);
       }
 
+      /*
+       * save PDB entries for sequence
+       */
       if (jdatasq.getAllPDBEntries() != null)
       {
         Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
@@ -1144,6 +1151,11 @@ public class Jalview2XML
 
       saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
 
+      if (jds.hasHMMProfile())
+      {
+        saveHmmerProfile(jout, jseq, jds);
+      }
+
       // jms.addJSeq(jseq);
       object.getJSeq().add(jseq);
     }
@@ -1501,11 +1513,14 @@ public class Jalview2XML
       view.setFollowHighlight(av.isFollowHighlight());
       view.setFollowSelection(av.followSelection);
       view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
+      view.setShowComplementFeatures(av.isShowComplementFeatures());
+      view.setShowComplementFeaturesOnTop(
+              av.isShowComplementFeaturesOnTop());
       if (av.getFeaturesDisplayed() != null)
       {
         FeatureSettings fs = new FeatureSettings();
 
-        FeatureRenderer fr = ap.getSeqPanel().seqCanvas
+        FeatureRendererModel fr = ap.getSeqPanel().seqCanvas
                 .getFeatureRenderer();
         String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
 
@@ -1688,7 +1703,39 @@ public class Jalview2XML
     }
     return object;
   }
+  /**
+   * Saves the HMMER profile associated with the sequence as a file in the jar,
+   * in HMMER format, and saves the name of the file as a child element of the
+   * XML sequence element
+   * 
+   * @param jout
+   * @param xmlSeq
+   * @param seq
+   */
+  protected void saveHmmerProfile(JarOutputStream jout, JSeq xmlSeq,
+          SequenceI seq)
+  {
+    HiddenMarkovModel profile = seq.getHMM();
+    if (profile == null)
+    {
+      warn("Want to save HMM profile for " + seq.getName()
+              + " but none found");
+      return;
+    }
+    HMMFile hmmFile = new HMMFile(profile);
+    String hmmAsString = hmmFile.print();
+    String jarEntryName = HMMER_PREFIX + nextCounter();
+    try
+    {
+      writeJarEntry(jout, jarEntryName, hmmAsString.getBytes());
+      xmlSeq.setHmmerProfile(jarEntryName);
+    } catch (IOException e)
+    {
+      warn("Error saving HMM profile: " + e.getMessage());
+    }
+  }
 
+    
   /**
    * Writes PCA viewer attributes and computed values to an XML model object and
    * adds it to the JalviewModel. Any exceptions are reported by logging.
@@ -2082,9 +2129,9 @@ public class Jalview2XML
       }
       else if (!matchedFile.equals(pdbentry.getFile()))
       {
-        Cache.log.warn(
-                "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
-                        + pdbentry.getFile());
+         Cache.log.warn(
+                  "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
+                          + pdbentry.getFile());
       }
       // record the
       // file so we
@@ -2399,7 +2446,7 @@ public class Jalview2XML
           argList = parmSet.getArguments();
           parmSet = null;
         }
-        AAConSettings settings = new AAConSettings(
+        AutoCalcSetting settings = new AAConSettings(
                 calcIdParam.isAutoUpdate(), service, parmSet, argList);
         av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
                 calcIdParam.isNeedsUpdate());
@@ -3160,25 +3207,25 @@ public class Jalview2XML
    * @param prefix
    *          a prefix for the temporary file name, must be at least three
    *          characters long
-   * @param origFile
+   * @param suffixModel
    *          null or original file - so new file can be given the same suffix
    *          as the old one
    * @return
    */
   protected String copyJarEntry(jarInputStreamProvider jprovider,
-          String jarEntryName, String prefix, String origFile)
+          String jarEntryName, String prefix, String suffixModel)
   {
     BufferedReader in = null;
     PrintWriter out = null;
     String suffix = ".tmp";
-    if (origFile == null)
+    if (suffixModel == null)
     {
-      origFile = jarEntryName;
+      suffixModel = jarEntryName;
     }
-    int sfpos = origFile.lastIndexOf(".");
-    if (sfpos > -1 && sfpos < (origFile.length() - 3))
+    int sfpos = suffixModel.lastIndexOf(".");
+    if (sfpos > -1 && sfpos < (suffixModel.length() - 1))
     {
-      suffix = "." + origFile.substring(sfpos + 1);
+      suffix = "." + suffixModel.substring(sfpos + 1);
     }
     try
     {
@@ -3583,6 +3630,18 @@ public class Jalview2XML
             }
           }
         }
+
+        /*
+         * load any HMMER profile
+         */
+        // TODO fix this
+
+        String hmmJarFile = jseqs.get(i).getHmmerProfile();
+        if (hmmJarFile != null && jprovider != null)
+        {
+          loadHmmerProfile(jprovider, hmmJarFile, al.getSequenceAt(i));
+        }
+
       }
     } // end !multipleview
 
@@ -4057,6 +4116,31 @@ public class Jalview2XML
   }
 
   /**
+   * Loads a HMMER profile from a file stored in the project, and associates it
+   * with the specified sequence
+   * 
+   * @param jprovider
+   * @param hmmJarFile
+   * @param seq
+   */
+  protected void loadHmmerProfile(jarInputStreamProvider jprovider,
+          String hmmJarFile, SequenceI seq)
+  {
+    try
+    {
+      String hmmFile = copyJarEntry(jprovider, hmmJarFile, "hmm", null);
+      HMMFile parser = new HMMFile(hmmFile, DataSourceType.FILE);
+      HiddenMarkovModel hmmModel = parser.getHMM();
+      hmmModel = new HiddenMarkovModel(hmmModel, seq);
+      seq.setHMM(hmmModel);
+    } catch (IOException e)
+    {
+      warn("Error loading HMM profile for " + seq.getName() + ": "
+              + e.getMessage());
+    }
+  }
+
+  /**
    * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
    * panel is restored from separate jar entries, two (gapped and trimmed) per
    * sequence and secondary structure.
@@ -4444,7 +4528,7 @@ public class Jalview2XML
      */
     String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
     chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
-            "chimera", null);
+            "chimera", ".py");
 
     Set<Entry<File, StructureData>> fileData = data.getFileData()
             .entrySet();
@@ -5019,11 +5103,14 @@ public class Jalview2XML
     viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
     viewport.setShowGroupConsensus(view.isShowGroupConsensus());
     viewport.setShowGroupConservation(view.isShowGroupConservation());
+    viewport.setShowComplementFeatures(view.isShowComplementFeatures());
+    viewport.setShowComplementFeaturesOnTop(
+            view.isShowComplementFeaturesOnTop());
 
     // recover feature settings
     if (jm.getFeatureSettings() != null)
     {
-      FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
+      FeatureRendererModel fr = af.alignPanel.getSeqPanel().seqCanvas
               .getFeatureRenderer();
       FeaturesDisplayed fdi;
       viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
@@ -5441,10 +5528,10 @@ public class Jalview2XML
     String id = object.getViewport().get(0).getSequenceSetId();
     if (skipList.containsKey(id))
     {
-      if (Cache.log != null && Cache.log.isDebugEnabled())
-      {
-        Cache.log.debug("Skipping seuqence set id " + id);
-      }
+       if (Cache.log != null && Cache.log.isDebugEnabled())
+        {
+          Cache.log.debug("Skipping seuqence set id " + id);
+        }
       return true;
     }
     return false;
@@ -5918,7 +6005,6 @@ public class Jalview2XML
         jmap.setTo(djs);
         incompleteSeqs.put(sqid, djs);
         seqRefIds.put(sqid, djs);
-
       }
       jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
       addDBRefs(djs, ms);
@@ -6102,7 +6188,7 @@ public class Jalview2XML
       }
       else
       {
-        Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
+          Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
       }
     }
   }
@@ -6576,7 +6662,7 @@ public class Jalview2XML
         maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
       } catch (Exception e)
       {
-        Cache.log.warn("Couldn't parse out graduated feature color.", e);
+          Cache.log.warn("Couldn't parse out graduated feature color.", e);
       }
   
       NoValueColour noCol = colourModel.getNoValueColour();