JAL-4269 Now using --width, --height, --scale for both --image and --structureimage...
[jalview.git] / src / jalview / bin / Commands.java
index ba72831..3173b35 100644 (file)
@@ -17,7 +17,6 @@ import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Jalview.ExitCode;
 import jalview.bin.argparser.Arg;
 import jalview.bin.argparser.ArgParser;
-import jalview.bin.argparser.ArgParser.Position;
 import jalview.bin.argparser.ArgValue;
 import jalview.bin.argparser.ArgValuesMap;
 import jalview.bin.argparser.SubVals;
@@ -55,6 +54,7 @@ import jalview.util.ImageMaker;
 import jalview.util.ImageMaker.TYPE;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
+import jalview.util.StringUtils;
 import jalview.util.imagemaker.BitmapImageSizing;
 
 public class Commands
@@ -290,29 +290,14 @@ public class Commands
             }
           }
 
-          // colour alignment?
-          String colour = ArgParser.getFromSubValArgOrPref(avm, av,
-                  Arg.COLOUR, sv, null, "DEFAULT_COLOUR_PROT", "");
-          if ("" != colour)
-          {
-            ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
-                    af.getViewport(), af.getViewport().getAlignment(),
-                    colour);
-
-            if (cs == null && !"None".equals(colour))
-            {
-              addWarn("Couldn't parse '" + colour + "' as a colourscheme.");
-            }
-            else
-            {
-              af.changeColour(cs);
-            }
-            Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour);
-          }
+          // colour alignment
+          String colour = avm.getFromSubValArgOrPref(av, Arg.COLOUR, sv,
+                  null, "DEFAULT_COLOUR_PROT", "");
+          this.colourAlignFrame(af, colour);
 
           // Change alignment frame title
-          String title = ArgParser.getFromSubValArgOrPref(avm, av,
-                  Arg.TITLE, sv, null, null, null);
+          String title = avm.getFromSubValArgOrPref(av, Arg.TITLE, sv, null,
+                  null, null);
           if (title != null)
           {
             af.setTitle(title);
@@ -320,7 +305,7 @@ public class Commands
           }
 
           // Add features
-          String featuresfile = ArgParser.getValueFromSubValOrArg(avm, av,
+          String featuresfile = avm.getValueFromSubValOrArg(av,
                   Arg.FEATURES, sv);
           if (featuresfile != null)
           {
@@ -331,8 +316,8 @@ public class Commands
           }
 
           // Add annotations from file
-          String annotationsfile = ArgParser.getValueFromSubValOrArg(avm,
-                  av, Arg.ANNOTATIONS, sv);
+          String annotationsfile = avm.getValueFromSubValOrArg(av,
+                  Arg.ANNOTATIONS, sv);
           if (annotationsfile != null)
           {
             af.loadJalviewDataFile(annotationsfile, null, null, null);
@@ -342,8 +327,8 @@ public class Commands
           }
 
           // Set or clear the sortbytree flag
-          boolean sortbytree = ArgParser.getBoolFromSubValOrArg(avm,
-                  Arg.SORTBYTREE, sv);
+          boolean sortbytree = avm.getBoolFromSubValOrArg(Arg.SORTBYTREE,
+                  sv);
           if (sortbytree)
           {
             af.getViewport().setSortByTree(true);
@@ -351,8 +336,7 @@ public class Commands
           }
 
           // Load tree from file
-          String treefile = ArgParser.getValueFromSubValOrArg(avm, av,
-                  Arg.TREE, sv);
+          String treefile = avm.getValueFromSubValOrArg(av, Arg.TREE, sv);
           if (treefile != null)
           {
             try
@@ -371,13 +355,13 @@ public class Commands
           }
 
           // Show secondary structure annotations?
-          boolean showSSAnnotations = ArgParser.getFromSubValArgOrPref(avm,
+          boolean showSSAnnotations = avm.getFromSubValArgOrPref(
                   Arg.SHOWSSANNOTATIONS, av.getSubVals(), null,
                   "STRUCT_FROM_PDB", true);
           af.setAnnotationsVisibility(showSSAnnotations, true, false);
 
           // Show sequence annotations?
-          boolean showAnnotations = ArgParser.getFromSubValArgOrPref(avm,
+          boolean showAnnotations = avm.getFromSubValArgOrPref(
                   Arg.SHOWANNOTATIONS, av.getSubVals(), null,
                   "SHOW_ANNOTATIONS", true);
           af.setAnnotationsVisibility(showAnnotations, false, true);
@@ -395,7 +379,7 @@ public class Commands
           }
 
           // wrap alignment? do this last for formatting reasons
-          wrap = ArgParser.getFromSubValArgOrPref(avm, Arg.WRAP, sv, null,
+          wrap = avm.getFromSubValArgOrPref(Arg.WRAP, sv, null,
                   "WRAP_ALIGNMENT", false);
           // af.setWrapFormat(wrap) is applied after structures are opened for
           // annotation reasons
@@ -456,6 +440,7 @@ public class Commands
         {
           String val = av.getValue();
           SubVals subVals = av.getSubVals();
+          int argIndex = av.getArgIndex();
           SequenceI seq = getSpecifiedSequence(af, avm, av);
           if (seq == null)
           {
@@ -526,10 +511,9 @@ public class Commands
           String structureFilepath = structureFile.getAbsolutePath();
 
           // get PAEMATRIX file and label from subvals or Arg.PAEMATRIX
-          String paeFilepath = ArgParser
-                  .getFromSubValArgOrPrefWithSubstitutions(argParser, avm,
-                          Arg.PAEMATRIX, Position.AFTER, av, subVals, null,
-                          null, null);
+          String paeFilepath = avm.getFromSubValArgOrPrefWithSubstitutions(
+                  argParser, Arg.PAEMATRIX, ArgValuesMap.Position.AFTER, av,
+                  subVals, null, null, null);
           if (paeFilepath != null)
           {
             File paeFile = new File(paeFilepath);
@@ -546,19 +530,17 @@ public class Commands
           }
 
           // showing annotations from structure file or not
-          boolean ssFromStructure = ArgParser.getFromSubValArgOrPref(avm,
+          boolean ssFromStructure = avm.getFromSubValArgOrPref(
                   Arg.SHOWSSANNOTATIONS, subVals, null, "STRUCT_FROM_PDB",
                   true);
 
           // get TEMPFAC type from subvals or Arg.TEMPFAC in case user Adds
           // reference annotations
-          String tftString = ArgParser
-                  .getFromSubValArgOrPrefWithSubstitutions(argParser, avm,
-                          Arg.TEMPFAC, Position.AFTER, av, subVals, null,
-                          null, null);
-          boolean notempfac = ArgParser.getFromSubValArgOrPref(avm,
-                  Arg.NOTEMPFAC, subVals, null, "ADD_TEMPFACT_ANN", false,
-                  true);
+          String tftString = avm.getFromSubValArgOrPrefWithSubstitutions(
+                  argParser, Arg.TEMPFAC, ArgValuesMap.Position.AFTER, av,
+                  subVals, null, null, null);
+          boolean notempfac = avm.getFromSubValArgOrPref(Arg.NOTEMPFAC,
+                  subVals, null, "ADD_TEMPFACT_ANN", false, true);
           TFType tft = notempfac ? null : TFType.DEFAULT;
           if (tftString != null && !notempfac)
           {
@@ -587,18 +569,18 @@ public class Commands
             }
           }
 
-          String sViewer = ArgParser.getFromSubValArgOrPref(avm,
-                  Arg.STRUCTUREVIEWER, Position.AFTER, av, subVals, null,
-                  null, "jmol");
-          ViewerType viewerType = ViewerType.getFromString(sViewer);
+          String sViewerName = avm.getFromSubValArgOrPref(
+                  Arg.STRUCTUREVIEWER, ArgValuesMap.Position.AFTER, av,
+                  subVals, null, null, "jmol");
+          ViewerType viewerType = ViewerType.getFromString(sViewerName);
 
           // TODO use ssFromStructure
-          StructureViewer sv = StructureChooser
+          StructureViewer structureViewer = StructureChooser
                   .openStructureFileForSequence(null, null, ap, seq, false,
                           structureFilepath, tft, paeFilepath, false,
                           ssFromStructure, false, viewerType);
 
-          if (sv == null)
+          if (structureViewer == null)
           {
             addError("Failed to import and open structure view for file '"
                     + structureFile + "'.");
@@ -607,17 +589,17 @@ public class Commands
           try
           {
             long tries = 1000;
-            while (sv.isBusy() && tries > 0)
+            while (structureViewer.isBusy() && tries > 0)
             {
               Thread.sleep(25);
-              if (sv.isBusy())
+              if (structureViewer.isBusy())
               {
                 tries--;
                 Console.debug(
                         "Waiting for viewer for " + structureFilepath);
               }
             }
-            if (tries == 0 && sv.isBusy())
+            if (tries == 0 && structureViewer.isBusy())
             {
               addWarn("Gave up waiting for structure viewer to load file '"
                       + structureFile
@@ -639,88 +621,106 @@ public class Commands
           {
             svMap.put(id, new ArrayList<>());
           }
-          svMap.get(id).add(sv);
+          svMap.get(id).add(structureViewer);
 
           Console.debug(
                   "Successfully opened viewer for " + structureFilepath);
-          String structureImageFilename = ArgParser.getValueFromSubValOrArg(
-                  avm, av, Arg.STRUCTUREIMAGE, subVals);
-          if (sv != null && structureImageFilename != null)
+
+          if (avm.containsArg(Arg.STRUCTUREIMAGE))
           {
-            ArgValue siAv = avm.getClosestNextArgValueOfArg(av,
-                    Arg.STRUCTUREIMAGE);
-            SubVals sisv = null;
-            if (structureImageFilename.equals(siAv.getValue()))
-            {
-              sisv = siAv.getSubVals();
-            }
-            File structureImageFile = new File(structureImageFilename);
-            String width = ArgParser.getValueFromSubValOrArg(avm, av,
-                    Arg.STRUCTUREIMAGEWIDTH, sisv);
-            String height = ArgParser.getValueFromSubValOrArg(avm, av,
-                    Arg.STRUCTUREIMAGEHEIGHT, sisv);
-            String scale = ArgParser.getValueFromSubValOrArg(avm, av,
-                    Arg.STRUCTUREIMAGESCALE, sisv);
-            String renderer = ArgParser.getValueFromSubValOrArg(avm, av,
-                    Arg.STRUCTUREIMAGETEXTRENDERER, sisv);
-            String typeS = ArgParser.getValueFromSubValOrArg(avm, av,
-                    Arg.STRUCTUREIMAGETYPE, sisv);
-            if (typeS == null || typeS.length() == 0)
-            {
-              typeS = FileUtils.getExtension(structureImageFile);
-            }
-            TYPE imageType;
-            try
-            {
-              imageType = Enum.valueOf(TYPE.class,
-                      typeS.toUpperCase(Locale.ROOT));
-            } catch (IllegalArgumentException e)
-            {
-              addWarn("Do not know image format '" + typeS
-                      + "', using PNG");
-              imageType = TYPE.PNG;
-            }
-            BitmapImageSizing userBis = ImageMaker
-                    .parseScaleWidthHeightStrings(scale, width, height);
-            // TODO MAKE THIS VIEWER INDEPENDENT!!
-            switch (StructureViewer.getViewerType())
+            for (ArgValue structureImageArgValue : avm
+                    .getArgValueList(Arg.STRUCTUREIMAGE))
             {
-            case JMOL:
-              JalviewStructureDisplayI sview = sv
-                      .getJalviewStructureDisplay();
-              if (sview instanceof AppJmol)
+              String structureImageFilename = structureImageArgValue
+                      .getValue();
+              if (structureViewer != null && structureImageFilename != null)
               {
-                AppJmol jmol = (AppJmol) sview;
+                SubVals structureImageSubVals = null;
+                structureImageSubVals = structureImageArgValue.getSubVals();
+                File structureImageFile = new File(structureImageFilename);
+                String width = avm.getValueFromSubValOrArg(
+                        structureImageArgValue, Arg.WIDTH,
+                        structureImageSubVals);
+                String height = avm.getValueFromSubValOrArg(
+                        structureImageArgValue, Arg.HEIGHT,
+                        structureImageSubVals);
+                String scale = avm.getValueFromSubValOrArg(
+                        structureImageArgValue, Arg.SCALE,
+                        structureImageSubVals);
+                String renderer = avm.getValueFromSubValOrArg(
+                        structureImageArgValue, Arg.TEXTRENDERER,
+                        structureImageSubVals);
+                String typeS = avm.getValueFromSubValOrArg(
+                        structureImageArgValue, Arg.TYPE,
+                        structureImageSubVals);
+                if (typeS == null || typeS.length() == 0)
+                {
+                  typeS = FileUtils.getExtension(structureImageFile);
+                }
+                TYPE imageType;
                 try
                 {
-                  boolean success = this.checksBeforeWritingToFile(avm,
-                          subVals, false, structureImageFilename,
-                          "structure image", isError);
-                  if (!success)
+                  imageType = Enum.valueOf(TYPE.class,
+                          typeS.toUpperCase(Locale.ROOT));
+                } catch (IllegalArgumentException e)
+                {
+                  addWarn("Do not know image format '" + typeS
+                          + "', using PNG");
+                  imageType = TYPE.PNG;
+                }
+                BitmapImageSizing userBis = ImageMaker
+                        .parseScaleWidthHeightStrings(scale, width, height);
+
+                String imageColour = avm.getValueFromSubValOrArg(
+                        structureImageArgValue, Arg.IMAGECOLOUR,
+                        structureImageSubVals);
+                ColourSchemeI originalColourScheme = this
+                        .getColourScheme(af);
+                this.colourAlignFrame(af, imageColour);
+
+                // TODO MAKE THIS VIEWER INDEPENDENT!!
+                switch (StructureViewer.getViewerType())
+                {
+                case JMOL:
+                  JalviewStructureDisplayI sview = structureViewer
+                          .getJalviewStructureDisplay();
+                  if (sview instanceof AppJmol)
                   {
-                    continue;
-                  }
+                    AppJmol jmol = (AppJmol) sview;
+                    try
+                    {
+                      boolean success = this.checksBeforeWritingToFile(avm,
+                              subVals, false, structureImageFilename,
+                              "structure image", isError);
+                      if (!success)
+                      {
+                        continue;
+                      }
+
+                      Console.debug(
+                              "Rendering image to " + structureImageFile);
+                      jmol.makePDBImage(structureImageFile, imageType,
+                              renderer, userBis);
+                      Console.debug("Finished Rendering image to "
+                              + structureImageFile);
+
+                    } catch (ImageOutputException ioexc)
+                    {
+                      addError("Unexpected error whilst exporting image to "
+                              + structureImageFile, ioexc);
+                      isError = true;
+                      continue;
+                    }
 
-                  Console.debug("Rendering image to " + structureImageFile);
-                  jmol.makePDBImage(structureImageFile, imageType, renderer,
-                          userBis);
-                  Console.debug("Finished Rendering image to "
-                          + structureImageFile);
-
-                } catch (ImageOutputException ioexc)
-                {
-                  addError("Unexpected error whilst exporting image to "
-                          + structureImageFile, ioexc);
-                  isError = true;
+                  }
+                  break;
+                default:
+                  addWarn("Cannot export image for structure viewer "
+                          + structureViewer.getViewerType() + " yet");
                   continue;
                 }
-
+                this.colourAlignFrame(af, originalColourScheme);
               }
-              break;
-            default:
-              addWarn("Cannot export image for structure viewer "
-                      + sv.getViewerType() + " yet");
-              continue;
             }
           }
         }
@@ -794,29 +794,29 @@ public class Commands
     Boolean isError = Boolean.valueOf(false);
     if (avm.containsArg(Arg.IMAGE))
     {
-      for (ArgValue av : avm.getArgValueList(Arg.IMAGE))
+      for (ArgValue imageAv : avm.getArgValueList(Arg.IMAGE))
       {
-        String val = av.getValue();
-        SubVals subVal = av.getSubVals();
-        String fileName = subVal.getContent();
+        String val = imageAv.getValue();
+        SubVals imageSubVals = imageAv.getSubVals();
+        String fileName = imageSubVals.getContent();
         File file = new File(fileName);
         String name = af.getName();
-        String renderer = ArgParser.getValueFromSubValOrArg(avm, av,
-                Arg.TEXTRENDERER, subVal);
+        String renderer = avm.getValueFromSubValOrArg(imageAv,
+                Arg.TEXTRENDERER, imageSubVals);
         if (renderer == null)
           renderer = "text";
         String type = "png"; // default
 
-        String scale = ArgParser.getValueFromSubValOrArg(avm, av, Arg.SCALE,
-                subVal);
-        String width = ArgParser.getValueFromSubValOrArg(avm, av, Arg.WIDTH,
-                subVal);
-        String height = ArgParser.getValueFromSubValOrArg(avm, av,
-                Arg.HEIGHT, subVal);
+        String scale = avm.getValueFromSubValOrArg(imageAv, Arg.SCALE,
+                imageSubVals);
+        String width = avm.getValueFromSubValOrArg(imageAv, Arg.WIDTH,
+                imageSubVals);
+        String height = avm.getValueFromSubValOrArg(imageAv, Arg.HEIGHT,
+                imageSubVals);
         BitmapImageSizing userBis = ImageMaker
                 .parseScaleWidthHeightStrings(scale, width, height);
 
-        type = ArgParser.getValueFromSubValOrArg(avm, av, Arg.TYPE, subVal);
+        type = avm.getValueFromSubValOrArg(imageAv, Arg.TYPE, imageSubVals);
         if (type == null && fileName != null)
         {
           for (String ext : new String[] { "svg", "png", "html", "eps" })
@@ -831,10 +831,15 @@ public class Commands
         Cache.setPropsAreReadOnly(true);
         Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false");
 
+        String imageColour = avm.getValueFromSubValOrArg(imageAv,
+                Arg.IMAGECOLOUR, imageSubVals);
+        ColourSchemeI originalColourScheme = this.getColourScheme(af);
+        this.colourAlignFrame(af, imageColour);
+
         Console.info("Writing " + file);
 
-        boolean success = checksBeforeWritingToFile(avm, subVal, false,
-                fileName, "image", isError);
+        boolean success = checksBeforeWritingToFile(avm, imageSubVals,
+                false, fileName, "image", isError);
         if (!success)
         {
           continue;
@@ -897,6 +902,8 @@ public class Commands
                   ioex);
           isError = true;
         }
+
+        this.colourAlignFrame(af, originalColourScheme);
       }
     }
     return !isError;
@@ -926,8 +933,8 @@ public class Commands
         File file = new File(fileName);
 
         String name = af.getName();
-        String format = ArgParser.getValueFromSubValOrArg(avm, av,
-                Arg.FORMAT, subVals);
+        String format = avm.getValueFromSubValOrArg(av, Arg.FORMAT,
+                subVals);
         FileFormats ffs = FileFormats.getInstance();
         List<String> validFormats = ffs.getWritableFormats(false);
 
@@ -987,9 +994,8 @@ public class Commands
           continue;
         }
 
-        boolean backups = ArgParser.getFromSubValArgOrPref(avm, Arg.BACKUPS,
-                subVals, null,
-                Platform.isHeadless() ? null : BackupFiles.ENABLED,
+        boolean backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVals,
+                null, Platform.isHeadless() ? null : BackupFiles.ENABLED,
                 !Platform.isHeadless());
 
         Console.info("Writing " + fileName);
@@ -1017,7 +1023,7 @@ public class Commands
           ArgValue av)
   {
     SubVals subVals = av.getSubVals();
-    ArgValue idAv = avm.getClosestNextArgValueOfArg(av, Arg.SEQID);
+    ArgValue idAv = avm.getClosestNextArgValueOfArg(av, Arg.SEQID, true);
     SequenceI seq = null;
     if (subVals == null && idAv == null)
       return null;
@@ -1077,6 +1083,36 @@ public class Commands
     return svs;
   }
 
+  private void colourAlignFrame(AlignFrame af, String colour)
+  {
+    // use string "none" to remove colour scheme
+    if (colour != null && "" != colour)
+    {
+      ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
+              af.getViewport(), af.getViewport().getAlignment(), colour);
+      if (cs == null && !StringUtils.equalsIgnoreCase(colour, "none"))
+      {
+        addWarn("Couldn't parse '" + colour + "' as a colourscheme.");
+      }
+      else
+      {
+        Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour);
+        colourAlignFrame(af, cs);
+      }
+    }
+  }
+
+  private void colourAlignFrame(AlignFrame af, ColourSchemeI cs)
+  {
+    // Note that cs == null removes colour scheme from af
+    af.changeColour(cs);
+  }
+
+  private ColourSchemeI getColourScheme(AlignFrame af)
+  {
+    return af.getViewport().getGlobalColourScheme();
+  }
+
   private void addInfo(String errorMessage)
   {
     Console.info(errorMessage);
@@ -1106,8 +1142,8 @@ public class Commands
   {
     File file = new File(filename);
 
-    boolean overwrite = ArgParser.getFromSubValArgOrPref(avm, Arg.OVERWRITE,
-            subVal, null, "OVERWRITE_OUTPUT", false);
+    boolean overwrite = avm.getFromSubValArgOrPref(Arg.OVERWRITE, subVal,
+            null, "OVERWRITE_OUTPUT", false);
     boolean stdout = false;
     boolean backups = false;
     if (includeBackups)
@@ -1116,8 +1152,8 @@ public class Commands
       // 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.
-      backups = ArgParser.getFromSubValArgOrPref(avm, Arg.BACKUPS, subVal,
-              null, Platform.isHeadless() ? null : BackupFiles.ENABLED,
+      backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVal, null,
+              Platform.isHeadless() ? null : BackupFiles.ENABLED,
               !Platform.isHeadless());
     }
 
@@ -1130,8 +1166,8 @@ public class Commands
       return false;
     }
 
-    boolean mkdirs = ArgParser.getFromSubValArgOrPref(avm, Arg.MKDIRS,
-            subVal, null, "MKDIRS_OUTPUT", false);
+    boolean mkdirs = avm.getFromSubValArgOrPref(Arg.MKDIRS, subVal, null,
+            "MKDIRS_OUTPUT", false);
 
     if (!FileUtils.checkParentDir(file, mkdirs))
     {