From: James Procter Date: Wed, 7 Jun 2023 16:16:01 +0000 (+0100) Subject: Merge branch 'patch/JAL-4195_cli_eps_export_npe' into develop X-Git-Tag: Release_2_11_4_0~213^2~22 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=388622051f3d669942d9df63557c7a1401d7ff6d;hp=b036a71275c547ea3875298480a9a61b36f80eae;p=jalview.git Merge branch 'patch/JAL-4195_cli_eps_export_npe' into develop --- diff --git a/help/help/html/features/clarguments-reference.html b/help/help/html/features/clarguments-reference.html index 0221a67..dd0bd52 100644 --- a/help/help/html/features/clarguments-reference.html +++ b/help/help/html/features/clarguments-reference.html @@ -244,7 +244,7 @@ - ‑‑title "string"" + ‑‑title "string" Specifies the title for the open alignment window as string. ✓ @@ -252,7 +252,7 @@ ‑‑colour name - Applies the colour scheme name to the open alignment window. Valid values for name are: + Applies the colour scheme name to the open alignment window. Valid values for name include:
clustal,
@@ -293,6 +293,11 @@ t-coffee-scores,
sequence-id. +
+
+ Names of user defined schemes will also work, and jalview colour scheme specifications like: +
+ ‑‑colour "D,E=red; K,R,H=0022FF; C,c=yellow" ✓ diff --git a/src/jalview/bin/Commands.java b/src/jalview/bin/Commands.java index 30fdc30..b9c04f5 100644 --- a/src/jalview/bin/Commands.java +++ b/src/jalview/bin/Commands.java @@ -44,6 +44,9 @@ import jalview.io.FileLoader; import jalview.io.HtmlSvgOutput; import jalview.io.IdentifyFile; import jalview.io.NewickFile; +import jalview.io.exceptions.ImageOutputException; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.ColourSchemeProperty; import jalview.structure.StructureImportSettings.TFType; import jalview.structure.StructureSelectionManager; import jalview.util.FileUtils; @@ -100,6 +103,16 @@ public class Commands theseArgsWereParsed &= processLinked(id); processGroovyScript(id); boolean processLinkedOkay = theseArgsWereParsed; + + // wait around until alignFrame isn't busy + AlignFrame af=afMap.get(id); + while (af!=null && af.getViewport().isCalcInProgress()) + { + try { + Thread.sleep(25); + } catch (Exception q) {}; + } + theseArgsWereParsed &= processImages(id); if (processLinkedOkay) theseArgsWereParsed &= processOutput(id); @@ -107,7 +120,7 @@ public class Commands // close ap if (avm.getBoolean(Arg.CLOSE)) { - AlignFrame af = afMap.get(id); + af = afMap.get(id); if (af != null) { af.closeMenuItem_actionPerformed(true); @@ -249,7 +262,15 @@ public class Commands Arg.COLOUR, sv, null, "DEFAULT_COLOUR_PROT", ""); if ("" != colour) { - af.changeColour_actionPerformed(colour); + ColourSchemeI cs = ColourSchemeProperty.getColourScheme( + af.getViewport(), af.getViewport().getAlignment(), colour); + + if (cs==null && !"None".equals(colour)) + { + Console.warn("Couldn't parse '"+colour+"' as a colourscheme."); + } else { + af.changeColour(cs); + } Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour); } @@ -717,7 +738,7 @@ public class Commands Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false"); Console.info("Writing " + file); - + try { switch (type) { @@ -738,6 +759,7 @@ public class Commands break; case "biojs": + Console.debug("Creating BioJS MSA Viwer HTML file: " + fileName); try { BioJsHTMLOutput.refreshVersionInfo( @@ -748,17 +770,16 @@ public class Commands } 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); + af.createEPS(file, name); break; case "imagemap": - af.createImageMap(file, name); Console.debug("Creating ImageMap file: " + fileName); + af.createImageMap(file, name); break; default: @@ -766,6 +787,9 @@ public class Commands + "' not known. Ignoring"); break; } + } catch (Exception ioex) { + Console.warn("Unexpected error during export",ioex); + } } } return true; diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index b29d9d7..e4f9ec6 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -1005,9 +1005,7 @@ public class Jalview ex.printStackTrace(System.err); } } - // TODO - load PDB structure(s) to alignment JAL-629 - // (associate with identical sequence in alignment, or a specified - // sequence) + if (groovyscript != null) { // Execute the groovy script after we've done all the rendering stuff @@ -1800,8 +1798,14 @@ public class Jalview } } - /* - * testoutput for string values + /****************************** + * + * TEST OUTPUT METHODS + * + ******************************/ + /** + * method for reporting string values parsed/processed during tests + * */ protected static void testoutput(ArgParser ap, Arg a, String s1, String s2) @@ -1825,6 +1829,10 @@ public class Jalview testoutput(true, a, s1, s2); } + /** + * method for reporting string values parsed/processed during tests + */ + protected static void testoutput(BootstrapArgs bsa, Arg a, String s1, String s2) { @@ -1849,6 +1857,9 @@ public class Jalview testoutput(true, a, s1, s2); } + /** + * report value set for string values parsed/processed during tests + */ private static void testoutput(boolean yes, Arg a, String s1, String s2) { if (yes && ((s1 == null && s2 == null) diff --git a/src/jalview/bin/argparser/Arg.java b/src/jalview/bin/argparser/Arg.java index f7588cb..2f25978 100644 --- a/src/jalview/bin/argparser/Arg.java +++ b/src/jalview/bin/argparser/Arg.java @@ -84,7 +84,7 @@ public enum Arg "Specifies the title for the open alignment window as string.", Opt.STRING, Opt.LINKED), COLOUR(Type.OPENING, "color", // being a bit soft on the Americans! - "Applies the colour scheme to the open alignment window. Valid values are:\n" + "Applies the colour scheme to the open alignment window. Valid values include:\n" + "clustal,\n" + "blosum62,\n" + "pc-identity,\n" + "zappo,\n" + "taylor,\n" + "gecos-flower,\n" + "gecos-blossom,\n" + "gecos-sunset,\n" @@ -93,7 +93,11 @@ public enum Arg + "turn-propensity,\n" + "buried-index,\n" + "nucleotide,\n" + "nucleotide-ambiguity,\n" + "purine-pyrimidine,\n" + "rna-helices,\n" - + "t-coffee-scores,\n" + "sequence-id.", + + "t-coffee-scores,\n" + "sequence-id.\n" + +"\n" + + "Names of user defined colourschemes will also work,\n" + +"and jalview colourscheme specifications like\n" + +"--colour=\"D,E=red; K,R,H=0022FF; C,c=yellow\"", Opt.STRING, Opt.LINKED, Opt.ALLOWALL), FEATURES(Type.OPENING, "Add a feature file or URL to the open alignment.", Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.ALLOWSUBSTITUTIONS), diff --git a/src/jalview/bin/argparser/ArgParser.java b/src/jalview/bin/argparser/ArgParser.java index 1558065c..907b1fa 100644 --- a/src/jalview/bin/argparser/ArgParser.java +++ b/src/jalview/bin/argparser/ArgParser.java @@ -52,77 +52,111 @@ public class ArgParser protected static final String NEGATESTRING = "no"; - // the default linked id prefix used for no id (not even square braces) + /** + * the default linked id prefix used for no id (ie when not even square braces + * are provided) + */ protected static final String DEFAULTLINKEDIDPREFIX = "JALVIEW:"; - // the linkedId string used to match all linkedIds seen so far + /** + * the linkedId string used to match all linkedIds seen so far + */ protected static final String MATCHALLLINKEDIDS = "*"; - // the linkedId string used to match all of the last --open'ed linkedIds + /** + * the linkedId string used to match all of the last --open'ed linkedIds + */ protected static final String MATCHOPENEDLINKEDIDS = "open*"; - // the counter added to the default linked id prefix + /** + * the counter added to the default linked id prefix + */ private int defaultLinkedIdCounter = 0; - // the substitution string used to use the defaultLinkedIdCounter + /** + * the substitution string used to use the defaultLinkedIdCounter + */ private static final String DEFAULTLINKEDIDCOUNTER = "{}"; - // the counter added to the default linked id prefix. NOW using - // linkedIdAutoCounter - // private int openLinkedIdCounter = 0; - - // the linked id prefix used for --open files. NOW the same as DEFAULT + /** + * the linked id prefix used for --open files. NOW the same as DEFAULT + */ protected static final String OPENLINKEDIDPREFIX = DEFAULTLINKEDIDPREFIX; - // the counter used for {n} substitutions + /** + * the counter used for {n} substitutions + */ private int linkedIdAutoCounter = 0; - // the linked id substitution string used to increment the idCounter (and use - // the incremented value) + /** + * the linked id substitution string used to increment the idCounter (and use + * the incremented value) + */ private static final String INCREMENTLINKEDIDAUTOCOUNTER = "{++n}"; - // the linked id substitution string used to use the idCounter + /** + * the linked id substitution string used to use the idCounter + */ private static final String LINKEDIDAUTOCOUNTER = "{n}"; - // the linked id substitution string used to use the filename extension of - // --append - // or --open + /** + * the linked id substitution string used to use the filename extension of + * --append or --open + */ private static final String LINKEDIDEXTENSION = "{extension}"; - // the linked id substitution string used to use the base filename of --append - // or --open + /** + * the linked id substitution string used to use the base filename of --append + */ + /** or --open */ private static final String LINKEDIDBASENAME = "{basename}"; - // the linked id substitution string used to use the dir path of --append - // or --open + /** + * the linked id substitution string used to use the dir path of --append or + * --open + */ private static final String LINKEDIDDIRNAME = "{dirname}"; - // the current argfile + /** + * the current argfile + */ private String argFile = null; - // the linked id substitution string used to use the dir path of the latest - // --argfile name + /** + * the linked id substitution string used to use the dir path of the latest + */ + /** --argfile name */ private static final String ARGFILEBASENAME = "{argfilebasename}"; - // the linked id substitution string used to use the dir path of the latest - // --argfile name + /** + * the linked id substitution string used to use the dir path of the latest + * --argfile name + */ private static final String ARGFILEDIRNAME = "{argfiledirname}"; - // flag to say whether {n} subtitutions in output filenames should be made. - // Turn on and off with --substitutions and --nosubstitutions - // Start with it on + /** + * flag to say whether {n} subtitutions in output filenames should be made. + * Turn on and off with --substitutions and --nosubstitutions Start with it on + */ private boolean substitutions = true; - // flag to say whether the default linkedId is the current default linked id - // or ALL linkedIds + /** + * flag to say whether the default linkedId is the current default linked id + * + * or ALL linkedIds + */ private boolean allLinkedIds = false; - // flag to say whether the default linkedId is the current default linked id - // or OPENED linkedIds + /** + * flag to say whether the default linkedId is the current default linked id + * or OPENED linkedIds + */ private boolean openedLinkedIds = false; - // flag to say whether the structure arguments should be applied to all - // structures with this linked id + /** + * flag to say whether the structure arguments should be applied to all + * structures with this linked id + */ private boolean allStructures = false; protected static final Map argMap; @@ -925,15 +959,19 @@ public class ArgParser FIRST, BEFORE, AFTER } - // get from following Arg of type a or subval of same name (lowercase) + /** + * get from following Arg of type a or subval of same name (lowercase) + */ public static String getValueFromSubValOrArg(ArgValuesMap avm, ArgValue av, Arg a, SubVals sv) { return getFromSubValArgOrPref(avm, av, a, sv, null, null, null); } - // get from following Arg of type a or subval key or preference pref or - // default def + /** + * get from following Arg of type a or subval key or preference pref or + * default def + */ public static String getFromSubValArgOrPref(ArgValuesMap avm, ArgValue av, Arg a, SubVals sv, String key, String pref, String def) { @@ -941,8 +979,10 @@ public class ArgParser def); } - // get from following(AFTER), first occurence of (FIRST) or previous (BEFORE) - // Arg of type a or subval key or preference pref or default def + /** + * get from following(AFTER), first occurence of (FIRST) or previous (BEFORE) + * Arg of type a or subval key or preference pref or default def + */ public static String getFromSubValArgOrPref(ArgValuesMap avm, Arg a, Position pos, ArgValue av, SubVals sv, String key, String pref, String def) @@ -1071,7 +1111,9 @@ public class ArgParser // the following methods look for the "*" linkedId and add the argvalue to all // linkedId ArgValues if it does. - // This version inserts the subvals sv into all created values + /** + * This version inserts the subvals sv into all created values + */ private void addValue(String linkedId, Type type, ArgValues avs, SubVals sv, String v, int argIndex, boolean doSubs) { @@ -1119,21 +1161,32 @@ public class ArgParser doSubs); } - /* + /** * The following operations look for the "*" and "open*" linkedIds and add the - * argvalue to all appropriate linkedId ArgValues if it does. - * If subvals are supplied, they are inserted into all new set values. + * argvalue to all appropriate linkedId ArgValues if it does. If subvals are + * supplied, they are inserted into all new set values. * - * @param op The ArgParser.Op operation - * @param linkedId The String linkedId from the ArgValuesMap - * @param type The Arg.Type to attach to this ArgValue - * @param avs The ArgValues for this linkedId - * @param sv Use these SubVals on the ArgValue - * @param merge Merge the SubVals with any existing on the value. False will replace unless sv is null - * @param v The value of the ArgValue (may contain subvals). - * @param b The boolean value of the ArgValue. - * @param argIndex The argIndex for the ArgValue. - * @param doSubs Whether to perform substitutions on the subvals and value. + * @param op + * The ArgParser.Op operation + * @param linkedId + * The String linkedId from the ArgValuesMap + * @param type + * The Arg.Type to attach to this ArgValue + * @param avs + * The ArgValues for this linkedId + * @param sv + * Use these SubVals on the ArgValue + * @param merge + * Merge the SubVals with any existing on the value. False will + * replace unless sv is null + * @param v + * The value of the ArgValue (may contain subvals). + * @param b + * The boolean value of the ArgValue. + * @param argIndex + * The argIndex for the ArgValue. + * @param doSubs + * Whether to perform substitutions on the subvals and value. */ private void argValueOperation(Op op, String linkedId, Type type, ArgValues avs, SubVals sv, boolean merge, String v, boolean b, diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index 6f2faae..1fcc591 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -3571,4 +3571,17 @@ public class Desktop extends jalview.jbgui.GDesktop jalview.bin.Console.debug(Cache.getStackTraceString(e)); } } + + /** + * closes the current instance window, disposes and forgets about it. + */ + public static void closeDesktop() + { + if (Desktop.instance != null) { + Desktop.instance.closeAll_actionPerformed(null); + Desktop.instance.setVisible(false); + Desktop.instance.dispose(); + Desktop.instance = null; + } + } } diff --git a/src/jalview/gui/ImageExporter.java b/src/jalview/gui/ImageExporter.java index 32704d6..e18ca86 100644 --- a/src/jalview/gui/ImageExporter.java +++ b/src/jalview/gui/ImageExporter.java @@ -220,8 +220,8 @@ public class ImageExporter messageId); } catch (Exception e) { - System.out.println(String.format("Error creating %s file: %s", type, - e.toString())); + jalview.bin.Console.error(String.format("Error creating %s file: %s", type, + e.toString()),e); setStatus(MessageManager.formatMessage("info.error_creating_file", type), messageId); } diff --git a/src/jalview/io/HTMLOutput.java b/src/jalview/io/HTMLOutput.java index ed80eb9..d659e2a 100644 --- a/src/jalview/io/HTMLOutput.java +++ b/src/jalview/io/HTMLOutput.java @@ -34,6 +34,7 @@ import jalview.datamodel.AlignExportSettingsAdapter; import jalview.datamodel.AlignmentExportData; import jalview.gui.AlignmentPanel; import jalview.gui.IProgressIndicator; +import jalview.io.exceptions.ImageOutputException; import jalview.util.MessageManager; public abstract class HTMLOutput implements Runnable @@ -302,12 +303,12 @@ public abstract class HTMLOutput implements Runnable return generatedFile; } - public void exportHTML(String outputFile) + public void exportHTML(String outputFile) throws ImageOutputException { exportHTML(outputFile, null); } - public void exportHTML(String outputFile, String renderer) + public void exportHTML(String outputFile, String renderer) throws ImageOutputException { setProgressMessage(MessageManager.formatMessage( "status.exporting_alignment_as_x_file", getDescription())); @@ -358,5 +359,5 @@ public abstract class HTMLOutput implements Runnable } // used to pass an option such as render to run - public abstract void run(String string); + public abstract void run(String string) throws ImageOutputException; } \ No newline at end of file diff --git a/src/jalview/io/exceptions/ImageOutputException.java b/src/jalview/io/exceptions/ImageOutputException.java new file mode 100644 index 0000000..bf06494 --- /dev/null +++ b/src/jalview/io/exceptions/ImageOutputException.java @@ -0,0 +1,36 @@ +package jalview.io.exceptions; + +/** + * wrapper for passing error messages and exceptions back to UI when image io goes wrong + * @author jprocter + * + */ +public class ImageOutputException extends Exception +{ + + public ImageOutputException() + { + } + + public ImageOutputException(String message) + { + super(message); + } + + public ImageOutputException(Throwable cause) + { + super(cause); + } + + public ImageOutputException(String message, Throwable cause) + { + super(message, cause); + } + + public ImageOutputException(String message, Throwable cause, + boolean enableSuppression, boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/src/jalview/workers/AlignCalcManager.java b/src/jalview/workers/AlignCalcManager.java index 08ef3a2..d81db8c 100644 --- a/src/jalview/workers/AlignCalcManager.java +++ b/src/jalview/workers/AlignCalcManager.java @@ -200,11 +200,20 @@ public class AlignCalcManager implements AlignCalcManagerI @Override public boolean isWorking() { + boolean working=false; synchronized (inProgress) { // System.err.println("isWorking "+hashCode()); - return inProgress.size() > 0; + working |= inProgress.size() > 0; } + synchronized (updating) + { + for (List workers : updating.values()) + { + working |= workers.size() > 0; + } + } + return working; } @Override diff --git a/test/jalview/bin/CommandsTest.java b/test/jalview/bin/CommandsTest.java index b4c927b..61892df 100644 --- a/test/jalview/bin/CommandsTest.java +++ b/test/jalview/bin/CommandsTest.java @@ -49,8 +49,15 @@ public class CommandsTest @AfterMethod(alwaysRun = true) public void tearDown() { - if (Desktop.instance != null) - Desktop.instance.closeAll_actionPerformed(null); + Desktop.closeDesktop(); + } + + public static void callJalviewMain(String[] args) { + if (Jalview.getInstance()!=null) { + Jalview.getInstance().doMain(args); + } else { + Jalview.main(args); + } } /* --setprops is currently disabled so this test won't work @@ -71,7 +78,7 @@ public class CommandsTest int numFrames, String[] sequences) { String[] args = (cmdLine + " --gui").split("\\s+"); - Jalview.main(args); + callJalviewMain(args); Commands cmds = Jalview.getInstance().getCommands(); Assert.assertNotNull(cmds); Assert.assertEquals(cmds.commandArgsProvided(), cmdArgs, @@ -111,7 +118,7 @@ public class CommandsTest { cleanupFiles(filenames); String[] args = (cmdLine + " --gui").split("\\s+"); - Jalview.main(args); + callJalviewMain(args); Commands cmds = Jalview.getInstance().getCommands(); Assert.assertNotNull(cmds); File lastFile = null; @@ -139,7 +146,7 @@ public class CommandsTest { cleanupFiles(filenames); String[] args = (cmdLine + " --gui").split("\\s+"); - Jalview.main(args); + callJalviewMain(args); Commands cmds = Jalview.getInstance().getCommands(); Assert.assertNotNull(cmds); File lastFile = null; @@ -297,7 +304,7 @@ public class CommandsTest String[] nonfilenames) { String[] args = (cmdLine + " --gui").split("\\s+"); - Jalview.main(args); + callJalviewMain(args); Commands cmds = Jalview.getInstance().getCommands(); Assert.assertNotNull(cmds); for (String filename : filenames) diff --git a/test/jalview/bin/CommandsTest2.java b/test/jalview/bin/CommandsTest2.java index 0a47700..0c2071a 100644 --- a/test/jalview/bin/CommandsTest2.java +++ b/test/jalview/bin/CommandsTest2.java @@ -51,8 +51,7 @@ public class CommandsTest2 @AfterMethod(alwaysRun = true) public void tearDown() { - if (Desktop.instance != null) - Desktop.instance.closeAll_actionPerformed(null); + Desktop.closeDesktop(); } @Test( @@ -65,7 +64,7 @@ public class CommandsTest2 { String[] args = cmdLine.split("\\s+"); - Jalview.main(args); + CommandsTest.callJalviewMain(args); try { // sleep for slow build server to open annotations and viewer windows