JAL-629 Fix --tempfac. Hide non-working --notempfac. Add --scale, --width, --height...
authorBen Soares <b.soares@dundee.ac.uk>
Thu, 11 May 2023 19:38:04 +0000 (20:38 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Thu, 11 May 2023 19:38:04 +0000 (20:38 +0100)
src/jalview/bin/Cache.java
src/jalview/bin/Commands.java
src/jalview/bin/Jalview.java
src/jalview/bin/argparser/Arg.java
src/jalview/bin/argparser/ArgParser.java
src/jalview/datamodel/annotations/AnnotationRowBuilder.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/ImageExporter.java
src/jalview/io/StructureFile.java
src/jalview/util/ImageMaker.java

index 769c868..f4c8854 100755 (executable)
@@ -383,10 +383,13 @@ public class Cache
         {
           // props file provided as URL
           fis = new URL(propertiesFile).openStream();
-          System.out.println(
-                  "Loading jalview properties from : " + propertiesFile);
-          System.out.println(
-                  "Disabling Jalview writing to user's local properties file.");
+          if (!Jalview.quiet())
+          {
+            System.out.println(
+                    "Loading jalview properties from : " + propertiesFile);
+            System.out.println(
+                    "Disabling Jalview writing to user's local properties file.");
+          }
           propsAreReadOnly = true;
         } catch (Exception ex)
         {
@@ -414,7 +417,8 @@ public class Cache
         fis.close();
       } catch (Exception ex)
       {
-        System.out.println("Error reading properties file: " + ex);
+        if (!Jalview.quiet())
+          System.out.println("Error reading properties file: " + ex);
       }
     }
 
@@ -470,7 +474,8 @@ public class Cache
       }
     } catch (Exception ex)
     {
-      System.out.println("Error reading author details: " + ex);
+      if (!Jalview.quiet())
+        System.out.println("Error reading author details: " + ex);
       authorDetails = null;
     }
     if (authorDetails == null)
@@ -554,10 +559,13 @@ public class Cache
               remoteVersion = remoteBuildProperties.getProperty("VERSION");
             } catch (Exception ex)
             {
-              System.out.println(
-                      "Non-fatal exception when checking version at "
-                              + remoteBuildPropertiesUrl + ":");
-              System.out.println(ex);
+              if (!Jalview.quiet())
+              {
+                System.out.println(
+                        "Non-fatal exception when checking version at "
+                                + remoteBuildPropertiesUrl + ":");
+                System.out.println(ex);
+              }
               remoteVersion = getProperty("VERSION");
             }
           }
@@ -656,7 +664,8 @@ public class Cache
       }
     } catch (Exception ex)
     {
-      System.out.println("Error reading build details: " + ex);
+      if (!Jalview.quiet())
+        System.out.println("Error reading build details: " + ex);
       applicationProperties.remove("VERSION");
     }
     String codeVersion = getProperty("VERSION");
@@ -676,11 +685,8 @@ public class Cache
     new BuildDetails(codeVersion, null, codeInstallation);
     if (printVersion && reportVersion)
     {
-      if (!Jalview.quiet())
-      {
-        System.out.println(ChannelProperties.getProperty("app_name")
-                + " Version: " + codeVersion + codeInstallation);
-      }
+      System.out.println(ChannelProperties.getProperty("app_name")
+              + " version: " + codeVersion + codeInstallation);
     }
   }
 
@@ -741,8 +747,9 @@ public class Cache
         def = Integer.parseInt(string);
       } catch (NumberFormatException e)
       {
-        System.out.println("Error parsing int property '" + property
-                + "' with value '" + string + "'");
+        if (!Jalview.quiet())
+          System.out.println("Error parsing int property '" + property
+                  + "' with value '" + string + "'");
       }
     }
 
@@ -783,8 +790,9 @@ public class Cache
       }
     } catch (Exception ex)
     {
-      System.out.println(
-              "Error setting property: " + key + " " + obj + "\n" + ex);
+      if (!Jalview.quiet())
+        System.out.println(
+                "Error setting property: " + key + " " + obj + "\n" + ex);
     }
     return oldValue;
   }
@@ -814,7 +822,8 @@ public class Cache
         out.close();
       } catch (Exception ex)
       {
-        System.out.println("Error saving properties: " + ex);
+        if (!Jalview.quiet())
+          System.out.println("Error saving properties: " + ex);
       }
     }
   }
@@ -1152,7 +1161,8 @@ public class Cache
         }
       } catch (Exception ex)
       {
-        System.out.println("Error loading User ColourFile\n" + ex);
+        if (!Jalview.quiet())
+          System.out.println("Error loading User ColourFile\n" + ex);
       }
     }
     if (!files.equals(coloursFound.toString()))
index 3608295..679fbf4 100644 (file)
@@ -492,16 +492,23 @@ public class Commands
 
           // 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.getBoolFromSubValOrArg(avm,
+                  Arg.NOTEMPFAC, subVals);
+          TFType tft = notempfac ? null : TFType.DEFAULT;
+          /*
           String tftString = subVals.get("tempfac");
-          TFType tft = avm.getBoolean(Arg.NOTEMPFAC) ? null
-                  : TFType.DEFAULT;
           ArgValue tftAv = getArgAssociatedWithStructure(Arg.TEMPFAC, avm,
                   af, structureFilepath);
           if (tftString == null && tftAv != null)
           {
             tftString = tftAv.getSubVals().getContent();
           }
-          if (tftString != null)
+          */
+          if (tftString != null && !notempfac)
           {
             // get kind of temperature factor annotation
             try
@@ -546,8 +553,9 @@ public class Commands
             }
           }
 
-          boolean addTempFac = tft != null
-                  || Cache.getDefault("ADD_TEMPFACT_ANN", false);
+          boolean addTempFac = notempfac ? false
+                  : ((tft != null)
+                          || Cache.getDefault("ADD_TEMPFACT_ANN", false));
 
           // TODO use ssFromStructure
           StructureChooser.openStructureFileForSequence(null, null, ap, seq,
@@ -626,6 +634,50 @@ public class Commands
         if (renderer == null)
           renderer = "text";
         String type = "png"; // default
+
+        float bitmapscale = 0.0f;
+        int bitmapwidth = 0;
+        int bitmapheight = 0;
+        String scale = ArgParser.getValueFromSubValOrArg(avm, av, Arg.SCALE,
+                subVal);
+        if (scale != null)
+        {
+          try
+          {
+            bitmapscale = Float.parseFloat(scale);
+          } catch (NumberFormatException e)
+          {
+            Console.warn("Did not understand scale '" + scale
+                    + "', won't be used.");
+          }
+        }
+        String width = ArgParser.getValueFromSubValOrArg(avm, av, Arg.WIDTH,
+                subVal);
+        if (width != null)
+        {
+          try
+          {
+            bitmapwidth = Integer.parseInt(width);
+          } catch (NumberFormatException e)
+          {
+            Console.warn("Did not understand width '" + width
+                    + "', won't be used.");
+          }
+        }
+        String height = ArgParser.getValueFromSubValOrArg(avm, av,
+                Arg.HEIGHT, subVal);
+        if (height != null)
+        {
+          try
+          {
+            bitmapheight = Integer.parseInt(height);
+          } catch (NumberFormatException e)
+          {
+            Console.warn("Did not understand height '" + height
+                    + "', won't be used.");
+          }
+        }
+
         type = ArgParser.getValueFromSubValOrArg(avm, av, Arg.TYPE, subVal);
         if (type == null && fileName != null)
         {
@@ -651,7 +703,7 @@ public class Commands
 
         case "png":
           Console.debug("Outputting type '" + type + "' to " + fileName);
-          af.createPNG(file);
+          af.createPNG(file, null, bitmapscale, bitmapwidth, bitmapheight);
           break;
 
         case "html":
index 1021a69..cf73c81 100755 (executable)
@@ -329,7 +329,8 @@ public class Jalview
         }
       }
 
-      if (bootstrapArgs.contains(Arg.HELP))
+      if (bootstrapArgs.contains(Arg.HELP)
+              || bootstrapArgs.contains(Arg.VERSION))
       {
         QUIET = true;
       }
@@ -354,12 +355,12 @@ public class Jalview
       }.start();
     }
 
-    if (!quiet())
+    if (!quiet() || bootstrapArgs.contains(Arg.VERSION))
     {
       System.out.println(
               "Java version: " + System.getProperty("java.version"));
-      System.out.println("Java Home: " + System.getProperty("java.home"));
-      System.out.println(System.getProperty("os.arch") + " "
+      System.out.println("Java home: " + System.getProperty("java.home"));
+      System.out.println("Java arch: " + System.getProperty("os.arch") + " "
               + System.getProperty("os.name") + " "
               + System.getProperty("os.version"));
 
@@ -390,7 +391,14 @@ public class Jalview
             .bootstrapProperties(bootstrapArgs.get(Arg.PROPS));
 
     // report Jalview version
-    Cache.loadBuildProperties(true);
+    Cache.loadBuildProperties(
+            !quiet() || bootstrapArgs.contains(Arg.VERSION));
+
+    // stop now if only after --version
+    if (bootstrapArgs.contains(Arg.VERSION))
+    {
+      Jalview.exit(null, 0);
+    }
 
     // old ArgsParser
     ArgsParser aparser = new ArgsParser(args);
index 95b6b43..6fcc011 100644 (file)
@@ -16,6 +16,9 @@ public enum Arg
 
   // Initialising arguments (BOOTSTRAP)
   HELP("Display this help statement", Opt.UNARY, Opt.BOOTSTRAP),
+  VERSION("Display the version of "
+          + ChannelProperties.getProperty("app_name"), Opt.UNARY,
+          Opt.BOOTSTRAP),
   HEADLESS(
           "Run Jalview in headless mode. No GUI interface will be created and Jalview will quit after all arguments have been processed.",
           Opt.UNARY, Opt.BOOTSTRAP),
@@ -99,7 +102,8 @@ public enum Arg
           Opt.STRING, Opt.LINKED, Opt.MULTI),
   NOTEMPFAC(
           "Do not show the temperature factor annotation for the preceding --structure.",
-          Opt.UNARY, Opt.LINKED),
+          Opt.UNARY, Opt.LINKED, Opt.SECRET), // keep this secret until it
+                                              // works!
   SHOWSSANNOTATIONS(null, Opt.BOOLEAN, Opt.LINKED),
 
   // Outputting files
@@ -114,6 +118,12 @@ public enum Arg
           "Sets whether text in a vector image format (SVG, HTML, EPS) should be rendered as text or vector line-art. Possible values for name are:\n"
                   + "text,\n" + "lineart.",
           Opt.STRING, Opt.LINKED, Opt.ALLOWALL),
+  SCALE("Sets a scaling for bitmap image format (PNG). Should be given as a floating point number. If used in conjunction with --width and --height then the smallest scaling will be used (scale, width and height provide bounds for the image).",
+          Opt.STRING, Opt.LINKED, Opt.ALLOWALL),
+  WIDTH("Sets a width for bitmap image format (PNG) with the height maintaining the aspect ratio. Should be given as a positive integer. If used in conjunction with --scale and --height then the smallest scaling will be used (scale, width and height provide bounds for the image).",
+          Opt.STRING, Opt.LINKED, Opt.ALLOWALL),
+  HEIGHT("Sets a height for bitmap image format (PNG) with the width maintaining the aspect ratio. Should be given as a positive integer. If used in conjunction with --scale and --width then the smallest scaling will be used (scale, width and height provide bounds for the image).",
+          Opt.STRING, Opt.LINKED, Opt.ALLOWALL),
   OUTPUT("Export the open alignment to file filename. The format name is specified by the subval modifier format=name, a following --format name argument or guessed from the file extension. Valid format names (and file extensions) are:\n"
           + "fasta (fa, fasta, mfa, fastq),\n" + "pfam (pfam),\n"
           + "stockholm (sto, stk),\n" + "pir (pir),\n" + "blc (blc),\n"
@@ -459,6 +469,11 @@ public enum Arg
         options.add("allows substitutions");
       }
 
+      if (a.hasOption(Opt.ALLOWALL))
+      {
+        options.add("can be applied to all linked arguments");
+      }
+
       if (a.hasOption(Opt.PRIVATE))
       {
         options.add("for internal use only");
index 38cb2d4..223cc53 100644 (file)
@@ -270,8 +270,10 @@ public class ArgParser
         {
           // arg not found
           Console.error("Argument '" + arg + "' not recognised.  Exiting.");
-          Jalview.exit("Unrecognised command line argument '" + arg + "'",
-                  13);
+          Jalview.exit("Invalid argument used." + System.lineSeparator()
+                  + "Use" + System.lineSeparator() + "jalview "
+                  + Arg.HELP.argString() + System.lineSeparator()
+                  + "for a usage statement.", 13);
           continue;
         }
         if (a.hasOption(Opt.PRIVATE) && !allowPrivate)
index b3d567a..c7e4549 100644 (file)
@@ -1,7 +1,6 @@
 package jalview.datamodel.annotations;
 
 import jalview.datamodel.Annotation;
-import jalview.structure.StructureImportSettings;
 import jalview.structure.StructureImportSettings.TFType;
 
 public class AnnotationRowBuilder
@@ -18,14 +17,15 @@ public class AnnotationRowBuilder
   /**
    * the type of temperature factor plot (if it is one)
    */
-  private StructureImportSettings.TFType tfType = StructureImportSettings.TFType.DEFAULT;
+  // private TFType tfType = TFType.DEFAULT;
+  private TFType tfType = null;
 
-  public void setTFType(StructureImportSettings.TFType t)
+  public void setTFType(TFType t)
   {
     tfType = t;
   }
 
-  public StructureImportSettings.TFType getTFType()
+  public TFType getTFType()
   {
     return tfType;
   }
@@ -97,7 +97,7 @@ public class AnnotationRowBuilder
     name = string;
   }
 
-  public AnnotationRowBuilder(String name, float min, float max, StructureImportSettings.TFType tft)
+  public AnnotationRowBuilder(String name, float min, float max, TFType tft)
   {
     this(name, min, max);
     setTFType(tft);
index 6b46041..71905c1 100644 (file)
@@ -1480,12 +1480,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void createPNG(File f)
   {
-    createPNG(f, null);
+    createPNG(f, null, 0.0f, 0, 0);
   }
 
-  public void createPNG(File f, String renderer)
+  public void createPNG(File f, String renderer, float bitmapscale,
+          int bitmapwidth, int bitmapheight)
   {
-    alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer);
+    alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, bitmapscale,
+            bitmapwidth, bitmapheight);
   }
 
   /**
index 3b0597a..a5a1aff 100644 (file)
@@ -1173,14 +1173,22 @@ public class AlignmentPanel extends GAlignmentPanel implements
     return (w > 0 ? w : calculateIdWidth().width);
   }
 
+  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer)
+  {
+    makeAlignmentImage(type, file, renderer, 0.0f, 0, 0);
+  }
+
   /**
    * Builds an image of the alignment of the specified type (EPS/PNG/SVG) and
    * writes it to the specified file
    * 
    * @param type
    * @param file
+   * @param textrenderer
+   * @param bitmapscale
    */
-  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer)
+  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer,
+          float bitmapscale, int bitmapwidth, int bitmapheight)
   {
     final int borderBottomOffset = 5;
 
@@ -1210,7 +1218,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     int imageWidth = aDimension.getWidth();
     int imageHeight = aDimension.getHeight() + borderBottomOffset;
     String of = MessageManager.getString("label.alignment");
-    exporter.doExport(file, this, imageWidth, imageHeight, of, renderer);
+    exporter.doExport(file, this, imageWidth, imageHeight, of, renderer,
+            bitmapscale, bitmapwidth, bitmapheight);
   }
 
   /**
index 657601e..785d206 100644 (file)
@@ -105,11 +105,12 @@ public class ImageExporter
   public void doExport(File file, Component parent, int width, int height,
           String imageSource)
   {
-    doExport(file, parent, width, height, imageSource, null);
+    doExport(file, parent, width, height, imageSource, null, 0.0f, 0, 0);
   }
 
   public void doExport(File file, Component parent, int width, int height,
-          String imageSource, String renderer)
+          String imageSource, String renderer, float bitmapscale,
+          int bitmapwidth, int bitmapheight)
   {
     final long messageId = System.currentTimeMillis();
     setStatus(
@@ -165,7 +166,7 @@ public class ImageExporter
       final File chosenFile = file;
       Callable<Void> okAction = () -> {
         exportImage(chosenFile, !textSelected.get(), width, height,
-                messageId);
+                messageId, bitmapscale, bitmapwidth, bitmapheight);
         return null;
       };
       LineartOptions epsOption = new LineartOptions(TYPE.EPS.getName(),
@@ -191,7 +192,8 @@ public class ImageExporter
        * character rendering not required, or preference already set 
        * - just do the export
        */
-      exportImage(file, !textSelected.get(), width, height, messageId);
+      exportImage(file, !textSelected.get(), width, height, messageId,
+              bitmapscale, bitmapwidth, bitmapheight);
     }
   }
 
@@ -207,7 +209,8 @@ public class ImageExporter
    * @param messageId
    */
   protected void exportImage(File chosenFile, boolean asLineart, int width,
-          int height, long messageId)
+          int height, long messageId, float bitmapscale, int bitmapwidth,
+          int bitmapheight)
   {
     String type = imageType.getName();
     try
@@ -217,7 +220,7 @@ public class ImageExporter
       // "status.exporting_alignment_as_x_file", type),
       // messageId);
       ImageMaker im = new ImageMaker(imageType, width, height, chosenFile,
-              title, asLineart);
+              title, asLineart, bitmapscale, bitmapwidth, bitmapheight);
       imageWriter.exportImage(im.getGraphics());
       im.writeImage();
       setStatus(
index fb416db..61b3d1d 100644 (file)
@@ -70,7 +70,7 @@ public abstract class StructureFile extends AlignFile
 
   private boolean pdbIdAvailable;
 
-  private StructureImportSettings.TFType temperatureFactorType = TFType.DEFAULT;
+  private TFType temperatureFactorType = TFType.DEFAULT;
 
   private String paeMatrix = null;
 
@@ -91,12 +91,12 @@ public abstract class StructureFile extends AlignFile
     return paeMatrix != null;
   }
 
-  public void setTemperatureFactorType(StructureImportSettings.TFType t)
+  public void setTemperatureFactorType(TFType t)
   {
     this.temperatureFactorType = t;
   }
 
-  public StructureImportSettings.TFType getTemperatureFactorType()
+  public TFType getTemperatureFactorType()
   {
     return temperatureFactorType;
   }
@@ -118,7 +118,7 @@ public abstract class StructureFile extends AlignFile
   }
 
   public StructureFile(Object inFile, DataSourceType sourceType,
-          StructureImportSettings.TFType tempfacType) throws IOException
+          TFType tempfacType) throws IOException
   {
     super(false, inFile, sourceType);
     this.setTemperatureFactorType(tempfacType);
index 0cd017f..016feee 100755 (executable)
@@ -20,8 +20,6 @@
  */
 package jalview.util;
 
-import jalview.io.JalviewFileChooser;
-
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.RenderingHints;
@@ -36,6 +34,8 @@ import org.jfree.graphics2d.svg.SVGGraphics2D;
 import org.jfree.graphics2d.svg.SVGHints;
 import org.jibble.epsgraphics.EpsGraphics2D;
 
+import jalview.io.JalviewFileChooser;
+
 public class ImageMaker
 {
   public static final String SVG_DESCRIPTION = "Scalable Vector Graphics";
@@ -110,10 +110,12 @@ public class ImageMaker
    * @param file
    * @param fileTitle
    * @param useLineart
+   * @param bitmapscale
    * @throws IOException
    */
   public ImageMaker(TYPE imageType, int width, int height, File file,
-          String fileTitle, boolean useLineart) throws IOException
+          String fileTitle, boolean useLineart, float bitmapscale,
+          int bitmapwidth, int bitmapheight) throws IOException
   {
     this.type = imageType;
 
@@ -127,7 +129,7 @@ public class ImageMaker
       setupEPS(width, height, fileTitle, useLineart);
       break;
     case PNG:
-      setupPNG(width, height);
+      setupPNG(width, height, bitmapscale, bitmapwidth, bitmapheight);
       break;
     default:
     }
@@ -176,14 +178,52 @@ public class ImageMaker
    * 
    * @param width
    * @param height
+   * @param scale
    */
-  protected void setupPNG(int width, int height)
+  protected void setupPNG(int width, int height, float scale,
+          int bitmapwidth, int bitmapheight)
   {
-    bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+    if (width == 0 || height == 0)
+      return;
+
+    float usescale = 0.0f;
+    int usewidth = width;
+    int useheight = height;
+
+    // use the smallest positive scale (i.e. fit in the box)
+    if (scale > 0.0f)
+    {
+      usescale = scale;
+      usewidth = Math.round(scale * width);
+      useheight = Math.round(scale * height);
+    }
+    if (bitmapwidth > 0)
+    {
+      float wscale = (float) bitmapwidth / width;
+      if (wscale > 0.0f && (usescale == 0.0f || wscale < usescale))
+      {
+        usescale = wscale;
+        usewidth = bitmapwidth;
+        useheight = Math.round(usescale * height);
+      }
+    }
+    if (bitmapheight > 0)
+    {
+      float hscale = (float) bitmapheight / height;
+      if (hscale > 0.0f && (usescale == 0.0f || hscale < usescale))
+      {
+        usescale = hscale;
+        usewidth = Math.round(usescale * width);
+        useheight = bitmapheight;
+      }
+    }
+    bi = new BufferedImage(usewidth, useheight, BufferedImage.TYPE_INT_RGB);
     graphics = bi.getGraphics();
     Graphics2D ig2 = (Graphics2D) graphics;
     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
             RenderingHints.VALUE_ANTIALIAS_ON);
+    if (usescale > 0.0f)
+      ig2.scale(usescale, usescale);
   }
 
   /**