JAL-629 Added linkedId to ArgValuesMap for reference. Updated Arg descriptions. Made...
[jalview.git] / src / jalview / bin / Commands.java
index f33202d..3608295 100644 (file)
@@ -2,6 +2,7 @@ package jalview.bin;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -31,13 +32,17 @@ import jalview.gui.StructureChooser;
 import jalview.gui.StructureViewer;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.AppletFormatAdapter;
+import jalview.io.BackupFiles;
+import jalview.io.BioJsHTMLOutput;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatException;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileLoader;
 import jalview.io.HtmlSvgOutput;
 import jalview.io.IdentifyFile;
+import jalview.io.NewickFile;
 import jalview.structure.StructureImportSettings.TFType;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.HttpUtils;
@@ -87,15 +92,12 @@ public class Commands
       {
         ArgValuesMap avm = argParser.getLinkedArgs(id);
         theseArgsWereParsed = true;
-        if (id == null)
-        {
-          theseArgsWereParsed &= processUnlinked(id);
-        }
-        else
-        {
-          theseArgsWereParsed &= processLinked(id);
-        }
+        theseArgsWereParsed &= processLinked(id);
+        processGroovyScript(id);
+        boolean processLinkedOkay = theseArgsWereParsed;
         theseArgsWereParsed &= processImages(id);
+        if (processLinkedOkay)
+          theseArgsWereParsed &= processOutput(id);
 
         // close ap
         if (avm.getBoolean(Arg.CLOSE))
@@ -110,7 +112,7 @@ public class Commands
       }
 
     }
-    if (argParser.getBool(Arg.QUIT))
+    if (argParser.getBoolean(Arg.QUIT))
     {
       Jalview.getInstance().quit();
       return true;
@@ -219,21 +221,11 @@ public class Commands
         if (af == null || "true".equals(av.getSubVal("new"))
                 || a == Arg.OPEN || format == FileFormat.Jalview)
         {
-          /*
-           * this approach isn't working yet // get default annotations before opening
-           * AlignFrame if (m.get(Arg.SSANNOTATIONS) != null) {
-           * Console.debug("##### SSANNOTATIONS=" + m.get(Arg.SSANNOTATIONS).getBoolean());
-           * } if (m.get(Arg.NOTEMPFAC) != null) { Console.debug( "##### NOTEMPFAC=" +
-           * m.get(Arg.NOTEMPFAC).getBoolean()); } boolean showSecondaryStructure =
-           * (m.get(Arg.SSANNOTATIONS) != null) ? m.get(Arg.SSANNOTATIONS).getBoolean() :
-           * false; boolean showTemperatureFactor = (m.get(Arg.NOTEMPFAC) != null) ?
-           * !m.get(Arg.NOTEMPFAC).getBoolean() : false; Console.debug("##### tempfac=" +
-           * showTemperatureFactor + ", showSS=" + showSecondaryStructure);
-           * StructureSelectionManager ssm = StructureSelectionManager
-           * .getStructureSelectionManager(Desktop.instance); if (ssm != null) {
-           * ssm.setAddTempFacAnnot(showTemperatureFactor);
-           * ssm.setProcessSecondaryStructure(showSecondaryStructure); }
-           */
+          if (a == Arg.OPEN)
+          {
+            Jalview.testoutput(argParser, Arg.OPEN, "examples/uniref50.fa",
+                    openFile);
+          }
 
           Console.debug(
                   "Opening '" + openFile + "' in new alignment frame");
@@ -241,46 +233,92 @@ public class Commands
 
           af = fileLoader.LoadFileWaitTillLoaded(openFile, protocol,
                   format);
-          boolean showAnnotations = ArgParser.getFromSubValArgOrPref(avm,
-                  Arg.ANNOTATIONS, av.getSubVals(), null,
-                  "SHOW_ANNOTATIONS", true);
-          af.setAnnotationsVisibility(showAnnotations, false, true);
 
           // wrap alignment?
           boolean wrap = ArgParser.getFromSubValArgOrPref(avm, Arg.WRAP, sv,
                   null, "WRAP_ALIGNMENT", false);
           af.getCurrentView().setWrapAlignment(wrap);
 
-          // colour aligment?
-          String colour = ArgParser.getFromSubValArgOrPref(avm, Arg.COLOUR,
-                  sv, null, "DEFAULT_COLOUR_PROT", "");
-
+          // colour alignment?
+          String colour = ArgParser.getFromSubValArgOrPref(avm, av,
+                  Arg.COLOUR, sv, null, "DEFAULT_COLOUR_PROT", "");
           if ("" != colour)
           {
             af.changeColour_actionPerformed(colour);
+            Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour);
           }
 
-          // change alignment frame title
-          String title = ArgParser.getFromSubValArgOrPref(avm, Arg.TITLE,
-                  sv, null, null, null);
+          // Change alignment frame title
+          String title = ArgParser.getFromSubValArgOrPref(avm, av,
+                  Arg.TITLE, sv, null, null, null);
           if (title != null)
+          {
             af.setTitle(title);
+            Jalview.testoutput(argParser, Arg.TITLE, "test title", title);
+          }
 
-          // show secondary structure annotations?
-          boolean showSSAnnotations = ArgParser.getFromSubValArgOrPref(avm,
-                  Arg.SSANNOTATIONS, av.getSubVals(), null,
-                  "STRUCT_FROM_PDB", true);
-          if (avm.getBoolean(Arg.SSANNOTATIONS))
+          // Add features
+          String featuresfile = ArgParser.getValueFromSubValOrArg(avm, av,
+                  Arg.FEATURES, sv);
+          if (featuresfile != null)
           {
-            af.setAnnotationsVisibility(showSSAnnotations, true, false);
-            /*
-            AlignmentUtils.showOrHideSequenceAnnotations(
-                    af.getCurrentView().getAlignment(),
-                    Collections.singleton("Secondary Structure"), null,
-                    false, false);
-             */
+            af.parseFeaturesFile(featuresfile,
+                    AppletFormatAdapter.checkProtocol(featuresfile));
+            Jalview.testoutput(argParser, Arg.FEATURES,
+                    "examples/testdata/plantfdx.features", featuresfile);
+          }
+
+          // Add annotations from file
+          String annotationsfile = ArgParser.getValueFromSubValOrArg(avm,
+                  av, Arg.ANNOTATIONS, sv);
+          if (annotationsfile != null)
+          {
+            af.loadJalviewDataFile(annotationsfile, null, null, null);
+            Jalview.testoutput(argParser, Arg.ANNOTATIONS,
+                    "examples/testdata/plantfdx.annotations",
+                    annotationsfile);
           }
 
+          // Set or clear the sortbytree flag
+          boolean sortbytree = ArgParser.getBoolFromSubValOrArg(avm,
+                  Arg.SORTBYTREE, sv);
+          if (sortbytree)
+          {
+            af.getViewport().setSortByTree(true);
+            Jalview.testoutput(argParser, Arg.SORTBYTREE);
+          }
+
+          // Load tree from file
+          String treefile = ArgParser.getValueFromSubValOrArg(avm, av,
+                  Arg.TREE, sv);
+          if (treefile != null)
+          {
+            try
+            {
+              NewickFile nf = new NewickFile(treefile,
+                      AppletFormatAdapter.checkProtocol(treefile));
+              af.getViewport().setCurrentTree(
+                      af.showNewickTree(nf, treefile).getTree());
+              Jalview.testoutput(argParser, Arg.TREE,
+                      "examples/testdata/uniref50_test_tree", treefile);
+            } catch (IOException e)
+            {
+              Console.warn("Couldn't add tree " + treefile, e);
+            }
+          }
+
+          // Show secondary structure annotations?
+          boolean showSSAnnotations = ArgParser.getFromSubValArgOrPref(avm,
+                  Arg.SHOWSSANNOTATIONS, av.getSubVals(), null,
+                  "STRUCT_FROM_PDB", true);
+          af.setAnnotationsVisibility(showSSAnnotations, true, false);
+
+          // Show sequence annotations?
+          boolean showAnnotations = ArgParser.getFromSubValArgOrPref(avm,
+                  Arg.SHOWANNOTATIONS, av.getSubVals(), null,
+                  "SHOW_ANNOTATIONS", true);
+          af.setAnnotationsVisibility(showAnnotations, false, true);
+
           // show temperature factor annotations?
           if (avm.getBoolean(Arg.NOTEMPFAC))
           {
@@ -292,33 +330,6 @@ public class Commands
                     af.getCurrentView().getAlignment(), hideThese, null,
                     false, false);
           }
-          else
-          /*
-           * comment out hacky approach up to here and add this line: if
-           * (showTemperatureFactor)
-           */
-          {
-            /*
-            if (avm.containsArg(Arg.TEMPFAC_LABEL))
-            {
-              AlignmentAnnotation aa = AlignmentUtils
-                      .getFirstSequenceAnnotationOfType(
-                              af.getCurrentView().getAlignment(),
-                              AlignmentAnnotation.LINE_GRAPH);
-              String label = avm.getValue(Arg.TEMPFAC_LABEL);
-              if (aa != null)
-              {
-                aa.label = label;
-              }
-              else
-              {
-                Console.info(
-                        "Could not find annotation to apply tempfac_label '"
-                                + label);
-              }
-            }
-            */
-          }
 
           // store the AlignFrame for this id
           afMap.put(id, af);
@@ -375,7 +386,7 @@ public class Commands
         {
           String val = av.getValue();
           SubVals subVals = av.getSubVals();
-          SequenceI seq = getSpecifiedSequence(af, subVals);
+          SequenceI seq = getSpecifiedSequence(af, avm, av);
           if (seq == null)
           {
             // Could not find sequence from subId, let's assume the first
@@ -455,17 +466,14 @@ public class Commands
           String structureFilepath = structureFile.getAbsolutePath();
 
           // get PAEMATRIX file and label from subvals or Arg.PAEMATRIX
-          String paeFilepath = subVals.getWithSubstitutions(argParser, id,
-                  "paematrix");
-          String paeLabel = subVals.get("paelabel");
-          ArgValue paeAv = getArgAssociatedWithStructure(Arg.PAEMATRIX, avm,
-                  af, structureFilepath);
-          if (paeFilepath == null && paeAv != null)
+          String paeFilepath = ArgParser
+                  .getFromSubValArgOrPrefWithSubstitutions(argParser, avm,
+                          Arg.PAEMATRIX, Position.AFTER, av, subVals, null,
+                          null, null);
+          if (paeFilepath != null)
           {
-            SubVals sv = paeAv.getSubVals();
-            File paeFile = new File(sv.getContent());
+            File paeFile = new File(paeFilepath);
 
-            paeLabel = sv.get("label");
             try
             {
               paeFilepath = paeFile.getCanonicalPath();
@@ -479,7 +487,7 @@ public class Commands
 
           // showing annotations from structure file or not
           boolean ssFromStructure = ArgParser.getFromSubValArgOrPref(avm,
-                  Arg.SSANNOTATIONS, subVals, null, "STRUCT_FROM_PDB",
+                  Arg.SHOWSSANNOTATIONS, subVals, null, "STRUCT_FROM_PDB",
                   true);
 
           // get TEMPFAC type from subvals or Arg.TEMPFAC in case user Adds
@@ -521,8 +529,8 @@ public class Commands
           }
 
           String sViewer = ArgParser.getFromSubValArgOrPref(avm,
-                  Arg.STRUCTUREVIEWER, Position.AFTER, av, subVals,
-                  "viewer", null, "jmol");
+                  Arg.STRUCTUREVIEWER, Position.AFTER, av, subVals, null,
+                  null, "jmol");
           ViewerType viewerType = null;
           if (!"none".equals(sViewer))
           {
@@ -569,6 +577,30 @@ public class Commands
     return theseArgsWereParsed;
   }
 
+  protected void processGroovyScript(String id)
+  {
+    ArgValuesMap avm = argParser.getLinkedArgs(id);
+    AlignFrame af = afMap.get(id);
+
+    if (af == null)
+    {
+      Console.warn("Did not have an alignment window for id=" + id);
+      return;
+    }
+
+    if (avm.containsArg(Arg.GROOVY))
+    {
+      String groovyscript = avm.getValue(Arg.GROOVY);
+      if (groovyscript != null)
+      {
+        // Execute the groovy script after we've done all the rendering stuff
+        // and before any images or figures are generated.
+        Console.info("Executing script " + groovyscript);
+        Jalview.getInstance().executeGroovyScript(groovyscript, af);
+      }
+    }
+  }
+
   protected boolean processImages(String id)
   {
     ArgValuesMap avm = argParser.getLinkedArgs(id);
@@ -586,16 +618,18 @@ public class Commands
       {
         String val = av.getValue();
         SubVals subVal = av.getSubVals();
-        String type = "png"; // default
         String fileName = subVal.getContent();
         File file = new File(fileName);
-        if (subVal.has("type"))
-        {
-          type = subVal.get("type");
-        }
-        else if (fileName != null)
+        String name = af.getName();
+        String renderer = ArgParser.getValueFromSubValOrArg(avm, av,
+                Arg.TEXTRENDERER, subVal);
+        if (renderer == null)
+          renderer = "text";
+        String type = "png"; // default
+        type = ArgParser.getValueFromSubValOrArg(avm, av, Arg.TYPE, subVal);
+        if (type == null && fileName != null)
         {
-          for (String ext : new String[] { "svg", "png", "html" })
+          for (String ext : new String[] { "svg", "png", "html", "eps" })
           {
             if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext))
             {
@@ -609,19 +643,47 @@ public class Commands
 
         switch (type)
         {
+
         case "svg":
           Console.debug("Outputting type '" + type + "' to " + fileName);
-          af.createSVG(file);
+          af.createSVG(file, renderer);
           break;
+
         case "png":
           Console.debug("Outputting type '" + type + "' to " + fileName);
           af.createPNG(file);
           break;
+
         case "html":
           Console.debug("Outputting type '" + type + "' to " + fileName);
           HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
-          htmlSVG.exportHTML(fileName);
+          htmlSVG.exportHTML(fileName, renderer);
           break;
+
+        case "biojs":
+          try
+          {
+            BioJsHTMLOutput.refreshVersionInfo(
+                    BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
+          } catch (URISyntaxException e)
+          {
+            e.printStackTrace();
+          }
+          BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
+          bjs.exportHTML(fileName);
+          Console.debug("Creating BioJS MSA Viwer HTML file: " + fileName);
+          break;
+
+        case "eps":
+          af.createEPS(file, name);
+          Console.debug("Creating EPS file: " + fileName);
+          break;
+
+        case "imagemap":
+          af.createImageMap(file, name);
+          Console.debug("Creating ImageMap file: " + fileName);
+          break;
+
         default:
           Console.warn(Arg.IMAGE.argString() + " type '" + type
                   + "' not known. Ignoring");
@@ -632,21 +694,147 @@ public class Commands
     return true;
   }
 
-  private SequenceI getSpecifiedSequence(AlignFrame af, SubVals subId)
+  protected boolean processOutput(String id)
   {
-    if (subId == null)
+    ArgValuesMap avm = argParser.getLinkedArgs(id);
+    AlignFrame af = afMap.get(id);
+
+    if (af == null)
+    {
+      Console.warn("Did not have an alignment window for id=" + id);
+      return false;
+    }
+
+    if (avm.containsArg(Arg.OUTPUT))
+    {
+      for (ArgValue av : avm.getArgValueList(Arg.OUTPUT))
+      {
+        String val = av.getValue();
+        SubVals subVals = av.getSubVals();
+        String fileName = subVals.getContent();
+        File file = new File(fileName);
+        boolean overwrite = ArgParser.getFromSubValArgOrPref(avm,
+                Arg.OVERWRITE, subVals, null, "OVERWRITE_OUTPUT", false);
+        // backups. Use the Arg.BACKUPS or subval "backups" setting first,
+        // otherwise if headless assume false, if not headless use the user
+        // preference with default true.
+        boolean backups = ArgParser.getFromSubValArgOrPref(avm, Arg.BACKUPS,
+                subVals, null,
+                Platform.isHeadless() ? null : BackupFiles.ENABLED,
+                !Platform.isHeadless());
+
+        // if backups is not true then --overwrite must be specified
+        if (file.exists() && !(overwrite || backups))
+        {
+          Console.error("Won't overwrite file '" + fileName + "' without "
+                  + Arg.OVERWRITE.argString() + " or "
+                  + Arg.BACKUPS.argString() + " set");
+          return false;
+        }
+
+        String name = af.getName();
+        String format = ArgParser.getValueFromSubValOrArg(avm, av,
+                Arg.FORMAT, subVals);
+        FileFormats ffs = FileFormats.getInstance();
+        List<String> validFormats = ffs.getWritableFormats(false);
+
+        FileFormatI ff = null;
+        if (format == null && fileName != null)
+        {
+          FORMAT: for (String fname : validFormats)
+          {
+            FileFormatI tff = ffs.forName(fname);
+            String[] extensions = tff.getExtensions().split(",");
+            for (String ext : extensions)
+            {
+              if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext))
+              {
+                ff = tff;
+                format = ff.getName();
+                break FORMAT;
+              }
+            }
+          }
+        }
+        if (ff == null && format != null)
+        {
+          ff = ffs.forName(format);
+        }
+        if (ff == null)
+        {
+          StringBuilder validSB = new StringBuilder();
+          for (String f : validFormats)
+          {
+            if (validSB.length() > 0)
+              validSB.append(", ");
+            validSB.append(f);
+            FileFormatI tff = ffs.forName(f);
+            validSB.append(" (");
+            validSB.append(tff.getExtensions());
+            validSB.append(")");
+          }
+
+          Jalview.exit("No valid format specified for "
+                  + Arg.OUTPUT.argString() + ". Valid formats are "
+                  + validSB.toString() + ".", 1);
+          // this return really shouldn't happen
+          return false;
+        }
+
+        String savedBackupsPreference = Cache
+                .getDefault(BackupFiles.ENABLED, null);
+        Console.debug("Setting backups to " + backups);
+        Cache.applicationProperties.put(BackupFiles.ENABLED,
+                Boolean.toString(backups));
+        af.saveAlignment(fileName, ff);
+        Console.debug("Returning backups to " + savedBackupsPreference);
+        if (savedBackupsPreference != null)
+          Cache.applicationProperties.put(BackupFiles.ENABLED,
+                  savedBackupsPreference);
+        if (af.isSaveAlignmentSuccessful())
+        {
+          Console.debug("Written alignment '" + name + "' in "
+                  + ff.getName() + " format to " + file);
+        }
+        else
+        {
+          Console.warn("Error writing file " + file + " in " + ff.getName()
+                  + " format!");
+        }
+
+      }
+    }
+    return true;
+  }
+
+  private SequenceI getSpecifiedSequence(AlignFrame af, ArgValuesMap avm,
+          ArgValue av)
+  {
+    SubVals subVals = av.getSubVals();
+    ArgValue idAv = avm.getClosestNextArgValueOfArg(av, Arg.SEQID);
+    SequenceI seq = null;
+    if (subVals == null && idAv == null)
       return null;
     AlignmentI al = af.getCurrentView().getAlignment();
-    if (subId.has("seqid"))
+    if (al == null)
+      return null;
+    if (subVals != null)
     {
-      return al.findName(subId.get("seqid"));
+      if (subVals.has(Arg.SEQID.getName()))
+      {
+        seq = al.findName(subVals.get(Arg.SEQID.getName()));
+      }
+      else if (-1 < subVals.getIndex()
+              && subVals.getIndex() < al.getSequences().size())
+      {
+        seq = al.getSequenceAt(subVals.getIndex());
+      }
     }
-    else if (-1 < subId.getIndex()
-            && subId.getIndex() < al.getSequences().size())
+    else if (idAv != null)
     {
-      return al.getSequenceAt(subId.getIndex());
+      seq = al.findName(idAv.getValue());
     }
-    return null;
+    return seq;
   }
 
   // returns the first Arg value intended for the structure structFilename
@@ -677,9 +865,6 @@ public class Commands
             else
             {
               structfile = likelyStructure.getValue();
-              Console.debug(
-                      "##### Comparing closest previous structure argument '"
-                              + structfile + "'");
             }
           }
         }