From 1d1edb58c9ee8baec12686a512eb18d97b9bdba1 Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Tue, 23 May 2023 14:33:38 +0100 Subject: [PATCH] JAL-629 Added --structureimage code and formatting args/subvals. Added tests for structure image. Added docs for structure image. --- help/help/html/features/clarguments.html | 142 +++++++++++++++++++++++-- src/jalview/bin/Commands.java | 68 ++---------- src/jalview/bin/Jalview.java | 12 ++- src/jalview/bin/argparser/Arg.java | 25 +++-- src/jalview/bin/argparser/ArgParser.java | 130 ++++++++++++++++------ src/jalview/bin/argparser/ArgValue.java | 6 +- src/jalview/bin/argparser/ArgValuesMap.java | 28 +++++ src/jalview/bin/argparser/SubVals.java | 34 +++++- src/jalview/gui/AlignFrame.java | 7 +- src/jalview/gui/AppJmol.java | 10 +- src/jalview/gui/StructureChooser.java | 7 +- test/jalview/bin/CommandsTest.java | 70 ++++++++++++ test/jalview/bin/CommandsTest2.java | 17 ++- test/jalview/bin/argparser/ArgParserTest.java | 15 ++- 14 files changed, 442 insertions(+), 129 deletions(-) diff --git a/help/help/html/features/clarguments.html b/help/help/html/features/clarguments.html index 437392f..d1ee915 100644 --- a/help/help/html/features/clarguments.html +++ b/help/help/html/features/clarguments.html @@ -406,10 +406,36 @@ ✓ + + ‑‑close + Close the open alignment window. This occurs after other output, processing and image export arguments. This applies to the current open alignment -- to apply to all ‑‑output and ‑‑image files, use after ‑‑all. + + ✓ + + + + + +

Processing alignments

+ + + + + + + + + + + + + + +
argumentactionsub-value modifiers (optional)linked (optional)
‑‑groovy filenameProcess a groovy script in the file for the open alignment.
-

Outputting files

+

Outputting alignment files

@@ -484,6 +510,33 @@ + + + + + + + + + + + + + +
‑‑backups / ‑‑nobackupsEnable (or disable) writing backup files when saving an ‑‑output file. This applies to the current open alignment -- to apply to all ‑‑output and ‑‑image files, use after ‑‑all.
‑‑overwrite / ‑‑nooverwriteEnable (or disable) overwriting of output files without backups enabled. This applies to the current open alignment -- to apply to all ‑‑output and ‑‑image files, use after ‑‑all.
+ + +

Exporting image files

+ + + + + + + + + + - + - + @@ -565,23 +620,85 @@ +
argumentactionsub-value modifiers (optional)linked (optional)
‑‑image filename Output an image of the open alignment window. Format is specified by the sub-value modifier, a following ‑‑type argument or guessed from the file extension. Valid formats/extensions are:
@@ -539,14 +592,16 @@
‑‑scale numberSets a scaling for bitmap image format (PNG). Should be given as a floating point number. This can also be set as a sub-value modifier to the --image value. If used in conjunction with --width and --height then the smallest scaling will be used (scale, width and height provide bounds for the image).Sets a scaling for bitmap image format (PNG). Should be given as a floating point number. This can also be set as a sub-value modifier to the --image value. If used in conjunction with --width and --height then the smallest scaling will be used (scale, width and height provide bounds for the image). +
‑‑width numberSets a width for bitmap image format (PNG) with the height maintaining the aspect ratio. Should be given as a positive integer. This can also be set as a sub-value modifier to the --image value. If used in conjunction with --scale and --height then the smallest scaling will be used (scale, width and height provide bounds for the image).Sets a width for bitmap image format (PNG) with the height maintaining the aspect ratio. Should be given as a positive integer. This can also be set as a sub-value modifier to the --image value. If used in conjunction with --scale and --height then the smallest scaling will be used (scale, width and height provide bounds for the image). +
+ + +

Exporting 3D structure image files (jmol only)

+ + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + + + + + + + + @@ -647,6 +764,13 @@ + + + + + diff --git a/src/jalview/bin/Commands.java b/src/jalview/bin/Commands.java index 2d57bc4..3437bfd 100644 --- a/src/jalview/bin/Commands.java +++ b/src/jalview/bin/Commands.java @@ -19,7 +19,6 @@ 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.ArgValues; import jalview.bin.argparser.ArgValuesMap; import jalview.bin.argparser.SubVals; import jalview.datamodel.AlignmentI; @@ -502,8 +501,9 @@ public class Commands .getFromSubValArgOrPrefWithSubstitutions(argParser, avm, Arg.TEMPFAC, Position.AFTER, av, subVals, null, null, null); - boolean notempfac = ArgParser.getBoolFromSubValOrArg(avm, - Arg.NOTEMPFAC, subVals); + boolean notempfac = ArgParser.getFromSubValArgOrPref(avm, + Arg.NOTEMPFAC, subVals, null, "ADD_TEMPFACT_ANN", false, + true); TFType tft = notempfac ? null : TFType.DEFAULT; /* String tftString = subVals.get("tempfac"); @@ -559,10 +559,6 @@ public class Commands } } - boolean addTempFac = notempfac ? false - : ((tft != null) - || Cache.getDefault("ADD_TEMPFACT_ANN", false)); - // TODO use ssFromStructure StructureViewer sv = StructureChooser .openStructureFileForSequence(null, null, ap, seq, false, @@ -606,7 +602,7 @@ public class Commands } BitmapImageSizing userBis = ImageMaker .parseScaleWidthHeightStrings(scale, width, height); - switch (sv.getViewerType()) + switch (StructureViewer.getViewerType()) { case JMOL: try @@ -909,9 +905,15 @@ public class Commands SequenceI seq = null; if (subVals == null && idAv == null) return null; + if (af == null || af.getCurrentView() == null) + { + return null; + } AlignmentI al = af.getCurrentView().getAlignment(); if (al == null) + { return null; + } if (subVals != null) { if (subVals.has(Arg.SEQID.getName())) @@ -930,54 +932,4 @@ public class Commands } return seq; } - - // returns the first Arg value intended for the structure structFilename - // (in the given AlignFrame from the ArgValuesMap) - private ArgValue getArgAssociatedWithStructure(Arg arg, ArgValuesMap avm, - AlignFrame af, String structFilename) - { - if (af != null) - { - for (ArgValue av : avm.getArgValueList(arg)) - { - SubVals subVals = av.getSubVals(); - String structid = subVals.get("structid"); - String structfile = subVals.get("structfile"); - - // let's find a structure - if (structfile == null && structid == null) - { - ArgValue likelyStructure = avm.getClosestPreviousArgValueOfArg(av, - Arg.STRUCTURE); - if (likelyStructure != null) - { - SubVals sv = likelyStructure.getSubVals(); - if (sv != null && sv.has(ArgValues.ID)) - { - structid = sv.get(ArgValues.ID); - } - else - { - structfile = likelyStructure.getValue(); - } - } - } - - if (structfile == null && structid != null) - { - StructureSelectionManager ssm = StructureSelectionManager - .getStructureSelectionManager(Desktop.instance); - if (ssm != null) - { - structfile = ssm.findFileForPDBId(structid); - } - } - if (structfile != null && structfile.equals(structFilename)) - { - return av; - } - } - } - return null; - } } diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index 2716ce1..4fe822d 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -774,7 +774,17 @@ public class Jalview { if (headlessArg) { - Jalview.exit("Successfully completed commands in headless mode", 0); + if (argparser.getBoolean(Arg.NOQUIT)) + { + Console.warn( + "Completed " + Arg.HEADLESS.getName() + " commands, but " + + Arg.NOQUIT + " is set so not quitting!"); + } + else + { + Jalview.exit("Successfully completed commands in headless mode", + 0); + } } Console.info("Successfully completed commands"); } diff --git a/src/jalview/bin/argparser/Arg.java b/src/jalview/bin/argparser/Arg.java index 2354cdd..8bac623 100644 --- a/src/jalview/bin/argparser/Arg.java +++ b/src/jalview/bin/argparser/Arg.java @@ -131,8 +131,7 @@ public enum Arg NOTEMPFAC(Type.STRUCTURE, "Do not show the temperature factor annotation for the preceding --structure.", Opt.UNARY, Opt.LINKED, Opt.ALLOWALL, Opt.SECRET), // keep this secret - // until it - // works! + // until it works! SHOWSSANNOTATIONS(Type.STRUCTURE, null, Opt.BOOLEAN, Opt.LINKED, Opt.ALLOWALL), @@ -159,25 +158,24 @@ public enum Arg HEIGHT(Type.IMAGE, "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), - STRUCTUREIMAGE(Type.IMAGE, + STRUCTUREIMAGE(Type.STRUCTUREIMAGE, "Export an image of a 3D structure opened in JMOL", Opt.STRING, Opt.LINKED, Opt.MULTI), - - STRUCTUREIMAGETYPE(Type.IMAGE, + STRUCTUREIMAGETYPE(Type.STRUCTUREIMAGE, "Set the structure image format for the preceding --structureimage. Valid values are:\n" + "svg,\n" + "png,\n" + "eps,\n" + "html,\n" + "biojs.", Opt.STRING, Opt.LINKED, Opt.ALLOWALL), - STRUCTUREIMAGETEXTRENDERER(Type.IMAGE, - "Sets whether text in a vector structure image format (SVG, HTML, EPS) should be rendered as text or vector line-art. Possible values are:\n" + STRUCTUREIMAGETEXTRENDERER(Type.STRUCTUREIMAGE, + "Sets whether text in a vector structure image format (SVG, EPS) should be rendered as text or vector line-art. Possible values are:\n" + "text,\n" + "lineart.", Opt.STRING, Opt.LINKED, Opt.ALLOWALL), - STRUCTUREIMAGESCALE(Type.IMAGE, + STRUCTUREIMAGESCALE(Type.STRUCTUREIMAGE, "Sets a scaling for bitmap structure image format (PNG). Should be given as a floating point number. If used in conjunction with --structureimagewidth and --structureimageheight then the smallest scaling will be used (structureimagescale, structureimagewidth and structureimageheight provide bounds for the structure image).", Opt.STRING, Opt.LINKED, Opt.ALLOWALL), - STRUCTUREIMAGEWIDTH(Type.IMAGE, + STRUCTUREIMAGEWIDTH(Type.STRUCTUREIMAGE, "Sets a width for bitmap structure image format (PNG) with the height maintaining the aspect ratio. Should be given as a positive integer. If used in conjunction with --structureimagescale and --structureimageheight then the smallest scaling will be used (structureimagescale, structureimagewidth and structureimageheight provide bounds for the structure image).", Opt.STRING, Opt.LINKED, Opt.ALLOWALL), - STRUCTUREIMAGEHEIGHT(Type.IMAGE, + STRUCTUREIMAGEHEIGHT(Type.STRUCTUREIMAGE, "Sets a height for bitmap structure image format (PNG) with the width maintaining the aspect ratio. Should be given as a positive integer. If used in conjunction with --structureimagescale and --structureimagewidth then the smallest scaling will be used (structureimagescale, structureimagewidth and structureimageheight provide bounds for the structure image).", Opt.STRING, Opt.LINKED, Opt.ALLOWALL), @@ -243,6 +241,12 @@ public enum Arg QUIT(Type.FLOW, "After all files have been opened, appended and output, quit Jalview. In ‑‑headless mode this already happens.", Opt.UNARY), + NOQUIT(Type.FLOW, + "Secret arg to not quit after --headless mode for tests", + Opt.UNARY, Opt.SECRET), + ALLSTRUCTURES(Type.FLOW, + "Apply the following 3D structure formatting arguments to all structures within the open alignment.", + Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION), // secret options TESTOUTPUT(Type.CONFIG, @@ -342,6 +346,7 @@ public enum Arg PROCESS("arguments used to process an alignment once opened"), OUTPUT("arguments used to save data from a processed alignment"), IMAGE("arguments used to export an image of an alignment"), + STRUCTUREIMAGE("arguments used to export an image of an structure"), FLOW("arguments that control processing of the other arguments"), // ALL("all arguments"), // mostly just a place-holder for --help-all NONE, // mostly a place-holder for --help diff --git a/src/jalview/bin/argparser/ArgParser.java b/src/jalview/bin/argparser/ArgParser.java index 6d1251c..0a8b8d3 100644 --- a/src/jalview/bin/argparser/ArgParser.java +++ b/src/jalview/bin/argparser/ArgParser.java @@ -121,6 +121,10 @@ public class ArgParser // or OPENED linkedIds private boolean openedLinkedIds = false; + // 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; protected Map linkedArgs = new HashMap<>(); @@ -424,6 +428,10 @@ public class ArgParser openedLinkedIds = !negated; allLinkedIds = false; } + else if (a == Arg.ALLSTRUCTURES) + { + allStructures = !negated; + } if (a.hasOption(Opt.STORED)) { @@ -485,23 +493,26 @@ public class ArgParser + arg); } } - else if (linkedId.contains(LINKEDIDAUTOCOUNTER)) - { - // turn {n} to the autoCounter - autoCounterString = Integer.toString(linkedIdAutoCounter); - linkedId = linkedId.replace(LINKEDIDAUTOCOUNTER, - autoCounterString); - Console.debug( - "Changing linkedId to '" + linkedId + "' from " + arg); - } - else if (linkedId.contains(INCREMENTLINKEDIDAUTOCOUNTER)) + else { - // turn {++n} to the incremented autoCounter - autoCounterString = Integer.toString(++linkedIdAutoCounter); - linkedId = linkedId.replace(INCREMENTLINKEDIDAUTOCOUNTER, - autoCounterString); - Console.debug( - "Changing linkedId to '" + linkedId + "' from " + arg); + if (linkedId.contains(LINKEDIDAUTOCOUNTER)) + { + // turn {n} to the autoCounter + autoCounterString = Integer.toString(linkedIdAutoCounter); + linkedId = linkedId.replace(LINKEDIDAUTOCOUNTER, + autoCounterString); + Console.debug("Changing linkedId to '" + linkedId + "' from " + + arg); + } + if (linkedId.contains(INCREMENTLINKEDIDAUTOCOUNTER)) + { + // turn {++n} to the incremented autoCounter + autoCounterString = Integer.toString(++linkedIdAutoCounter); + linkedId = linkedId.replace(INCREMENTLINKEDIDAUTOCOUNTER, + autoCounterString); + Console.debug("Changing linkedId to '" + linkedId + "' from " + + arg); + } } } @@ -521,8 +532,9 @@ public class ArgParser } // check for unique id - SubVals idsv = new SubVals(val); - String id = idsv.get(ArgValues.ID); + SubVals subvals = new SubVals(val); + boolean addNewSubVals = false; + String id = subvals.get(ArgValues.ID); if (id != null && avm.hasId(a, id)) { Console.error("Argument '" + a.argString() @@ -530,10 +542,21 @@ public class ArgParser continue; } - /* TODO - * Change all avs.addValue() avs.setBoolean avs.setNegated() avs.incrementCount calls to checkfor linkedId == "*" - * DONE, need to check - */ + // set allstructures to all non-primary structure options in this linked + // id if --allstructures has been set + if (allStructures + && (a.getType() == Type.STRUCTURE + || a.getType() == Type.STRUCTUREIMAGE) + && !a.hasOption(Opt.PRIMARY)) + { + if (!subvals.has(Arg.ALLSTRUCTURES.getName())) + // && !subvals.has("structureid")) + { + subvals.put(Arg.ALLSTRUCTURES.getName(), "true"); + addNewSubVals = true; + } + } + ArgValues avs = avm.getOrCreateArgValues(a); // store appropriate String value(s) @@ -563,7 +586,9 @@ public class ArgParser } else { - addValue(linkedId, type, avs, val, argIndex, true); + // addValue(linkedId, type, avs, val, argIndex, true); + addValue(linkedId, type, avs, addNewSubVals ? subvals : null, + val, argIndex, true); } } else if (a.hasOption(Opt.BOOLEAN)) @@ -925,8 +950,23 @@ public class ArgParser else if (pos == Position.AFTER && avm.getClosestNextArgValueOfArg(av, a) != null) value = avm.getClosestNextArgValueOfArg(av, a).getValue(); + + // look for allstructures subval for Type.STRUCTURE* + Arg arg = av.getArg(); + if (value == null && arg.hasOption(Opt.PRIMARY) + && arg.getType() == Type.STRUCTURE + && !a.hasOption(Opt.PRIMARY) && (a.getType() == Type.STRUCTURE + || a.getType() == Type.STRUCTUREIMAGE)) + { + ArgValue av2 = avm.getArgValueOfArgWithSubValKey(a, + Arg.ALLSTRUCTURES.getName()); + if (av2 != null) + { + value = av2.getValue(); + } + } } - else + if (value == null) { value = pref != null ? Cache.getDefault(pref, def) : def; } @@ -942,6 +982,13 @@ public class ArgParser public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a, SubVals sv, String key, String pref, boolean def) { + return getFromSubValArgOrPref(avm, a, sv, key, pref, def, false); + } + + public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a, + SubVals sv, String key, String pref, boolean def, + boolean invertPref) + { if ((key == null && a == null) || (sv == null && a == null)) return false; @@ -995,7 +1042,8 @@ public class ArgParser return avm.getBoolean(a); // return preference or default - return pref != null ? Cache.getDefault(pref, def) : def; + boolean prefVal = pref != null ? Cache.getDefault(pref, def) : false; + return pref != null ? (invertPref ? !prefVal : prefVal) : def; } // the following methods look for the "*" linkedId and add the argvalue to all @@ -1039,13 +1087,35 @@ public class ArgParser ADDVALUE, SETBOOLEAN, SETNEGATED, INCREMENTCOUNT } - // 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. private void argValueOperation(Op op, String linkedId, Type type, ArgValues avs, SubVals sv, String v, boolean b, int argIndex, boolean doSubs) { + // default to merge subvals if subvals are provided + argValueOperation(op, linkedId, type, avs, sv, true, v, b, argIndex, + 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. + * + * @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, + int argIndex, boolean doSubs) + { Arg a = avs.arg(); List wildcardLinkedIds = null; @@ -1097,8 +1167,8 @@ public class ArgParser { if (doSubs) { - val = makeSubstitutions(v, id); - sv = new SubVals(sv, val); + sv = new SubVals(sv, val, merge); + val = makeSubstitutions(sv.getContent(), id); } tavs.addValue(sv, type, val, argIndex, true); } diff --git a/src/jalview/bin/argparser/ArgValue.java b/src/jalview/bin/argparser/ArgValue.java index f76b757..3467f61 100644 --- a/src/jalview/bin/argparser/ArgValue.java +++ b/src/jalview/bin/argparser/ArgValue.java @@ -19,8 +19,10 @@ public class ArgValue implements Comparable */ private Type type = null; - // This id is set by a subVal id= to identify the product of this ArgValue - // later. Set but not currently used. + /* + * This id is set by a subVal id= to identify the product of this ArgValue + * later. Set but not currently used. + */ private String id; private SubVals subVals; diff --git a/src/jalview/bin/argparser/ArgValuesMap.java b/src/jalview/bin/argparser/ArgValuesMap.java index 085099a..ab6fcc1 100644 --- a/src/jalview/bin/argparser/ArgValuesMap.java +++ b/src/jalview/bin/argparser/ArgValuesMap.java @@ -120,6 +120,33 @@ public class ArgValuesMap return m.keySet(); } + public ArgValue getArgValueOfArgWithSubValKey(Arg a, String svKey) + { + return getArgValueOfArgWithSubValKey(a, svKey, false); + } + + public ArgValue getArgValueOfArgWithSubValKey(Arg a, String svKey, + boolean last) + { + ArgValues avs = this.getArgValues(a); + if (avs == null) + { + return null; + } + List compareAvs = avs.getArgValueList(); + for (int i = 0; i < compareAvs.size(); i++) + { + int index = last ? compareAvs.size() - 1 - i : i; + ArgValue av = compareAvs.get(index); + SubVals sv = av.getSubVals(); + if (sv.has(svKey) && !sv.get(svKey).equals("false")) + { + return av; + } + } + return null; + } + public ArgValue getClosestPreviousArgValueOfArg(ArgValue thisAv, Arg a) { ArgValue closestAv = null; @@ -161,6 +188,7 @@ public class ArgValuesMap return closestAv; } + // TODO this is incomplete and currently unused (fortunately) public ArgValue[] getArgValuesReferringTo(String key, String value, Arg a) { // this looks for the *next* arg that *might* be referring back to diff --git a/src/jalview/bin/argparser/SubVals.java b/src/jalview/bin/argparser/SubVals.java index a03ec15..4d146d9 100644 --- a/src/jalview/bin/argparser/SubVals.java +++ b/src/jalview/bin/argparser/SubVals.java @@ -29,14 +29,42 @@ public class SubVals protected SubVals(SubVals sv, String c) { - if (sv == null) + this(sv, c, true); + } + + protected SubVals(SubVals sv, String c, boolean merge) + { + SubVals subvals; + if (merge) + { + SubVals vsv = new SubVals(c); + if (sv != null && sv.getSubValMap() != null) + { + for (String key : sv.getSubValMap().keySet()) + { + vsv.put(key, sv.get(key)); + } + } + if (sv != null && sv.getIndex() > 0) + { + vsv.index = sv.getIndex(); + } + subvals = vsv; + } + else + { + // replace + subvals = sv; + } + if (subvals == null) { this.subValMap = new HashMap<>(); } else { - this.subValMap = sv == null ? new HashMap<>() : sv.getSubValMap(); - this.index = sv.getIndex(); + this.subValMap = subvals == null ? new HashMap<>() + : subvals.getSubValMap(); + this.index = subvals.getIndex(); } this.content = c; } diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 37eaae7..160ee1a 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -982,7 +982,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, @Override public void setProgressBar(String message, long id) { - if (!Platform.isHeadless()) + if (!Platform.isHeadless() && progressBar != null) progressBar.setProgressBar(message, id); } @@ -990,7 +990,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, public void registerHandler(final long id, final IProgressIndicatorHandler handler) { - progressBar.registerHandler(id, handler); + if (progressBar != null) + progressBar.registerHandler(id, handler); } /** @@ -1000,7 +1001,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, @Override public boolean operationInProgress() { - return progressBar.operationInProgress(); + return progressBar == null ? false : progressBar.operationInProgress(); } /** diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index 806bfc1..b7bac37 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -452,10 +452,12 @@ public class AppJmol extends StructureViewerBase RenderingHints.VALUE_ANTIALIAS_ON); if (type == TYPE.PNG && usescale > 0.0f) { - // for a scaled image, this scales down a bigger image to increase - // resolution - - ig2.scale(1 / usescale, 1 / usescale); + // for a scaled image, this scales down a bigger image to give the + // right resolution + if (usescale > 0.0f) + { + ig2.scale(1 / usescale, 1 / usescale); + } } jmb.jmolViewer.antialiased = true; diff --git a/src/jalview/gui/StructureChooser.java b/src/jalview/gui/StructureChooser.java index 790873f..2b16495 100644 --- a/src/jalview/gui/StructureChooser.java +++ b/src/jalview/gui/StructureChooser.java @@ -1669,20 +1669,21 @@ public class StructureChooser extends GStructureChooser @Override public void setProgressBar(String message, long id) { - if (!Platform.isHeadless()) + if (!Platform.isHeadless() && progressBar != null) progressBar.setProgressBar(message, id); } @Override public void registerHandler(long id, IProgressIndicatorHandler handler) { - progressBar.registerHandler(id, handler); + if (progressBar != null) + progressBar.registerHandler(id, handler); } @Override public boolean operationInProgress() { - return progressBar.operationInProgress(); + return progressBar == null ? false : progressBar.operationInProgress(); } public JalviewStructureDisplayI getOpenedStructureViewer() diff --git a/test/jalview/bin/CommandsTest.java b/test/jalview/bin/CommandsTest.java index 20ccd11..7ed1ea3 100644 --- a/test/jalview/bin/CommandsTest.java +++ b/test/jalview/bin/CommandsTest.java @@ -105,6 +105,34 @@ public class CommandsTest lookForSequenceName("THIS_SEQUENCE_ID_DOESN'T_EXIST")); } + @Test(groups = "Functional", dataProvider = "structureImageOutputFiles") + public void structureImageOutputTest(String cmdLine, String[] filenames) + throws IOException + { + cleanupFiles(filenames); + String[] args = cmdLine.split("\\s+"); + Jalview.main(args); + Commands cmds = Jalview.getInstance().getCommands(); + Assert.assertNotNull(cmds); + File lastFile = null; + for (String filename : filenames) + { + File file = new File(filename); + Assert.assertTrue(file.exists(), "File '" + filename + + "' was not created by '" + cmdLine + "'"); + Assert.assertTrue(file.isFile(), "File '" + filename + + "' is not a file from '" + cmdLine + "'"); + Assert.assertTrue(Files.size(file.toPath()) > 0, "File '" + filename + + "' has no content from '" + cmdLine + "'"); + // make sure the successive output files get bigger! + if (lastFile != null) + Assert.assertTrue( + Files.size(file.toPath()) > Files.size(lastFile.toPath())); + } + cleanupFiles(filenames); + tearDown(); + } + @Test(groups = "Functional", dataProvider = "argfileOutputFiles") public void argFilesGlobAndSubstitutionsTest(String cmdLine, String[] filenames) throws IOException @@ -133,6 +161,48 @@ public class CommandsTest tearDown(); } + @DataProvider(name = "structureImageOutputFiles") + public Object[][] structureImageOutputFiles() + { + return new Object[][] { + // + { "--nonews --nosplash --open=./examples/test_fab41.result/sample.a2m " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--structureimage=" + testfiles + "/structureimage1.png " + + "--open=./examples/test_fab41.result/sample.a2m " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--structureimage=" + testfiles + + "/structureimage2.png --structureimagescale=1.5" + + "--open=./examples/test_fab41.result/sample.a2m " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--structureimage=" + testfiles + + "/structureimage3.png --structureimagescale=2.0", + new String[] + { testfiles + "/structureimage1.png", + testfiles + "/structureimage2.png", + testfiles + "/structureimage3.png" } }, + /* + { "--headless --noquit --open=./examples/test_fab41.result/sample.a2m " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--structureimage=" + testfiles + "/structureimage1.png " + + "--open=./examples/test_fab41.result/sample.a2m " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--structureimage=" + testfiles + + "/structureimage2.png --structureimagescale=1.5" + + "--open=./examples/test_fab41.result/sample.a2m " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--structureimage=" + testfiles + + "/structureimage3.png --structureimagescale=2.0", + new String[] + { testfiles + "/structureimage1.png", + testfiles + "/structureimage2.png", + testfiles + "/structureimage3.png" } }, + */ + // + }; + + } + @DataProvider(name = "argfileOutputFiles") public Object[][] argfileOutputFiles() { diff --git a/test/jalview/bin/CommandsTest2.java b/test/jalview/bin/CommandsTest2.java index bd63232..a31b77d 100644 --- a/test/jalview/bin/CommandsTest2.java +++ b/test/jalview/bin/CommandsTest2.java @@ -131,8 +131,7 @@ public class CommandsTest2 String cmdLine, int seqNum, int annNum, - int viewerNum, - String propsFile + int structureViewerNum, */ return new Object[][] { // @@ -182,6 +181,20 @@ public class CommandsTest2 16, 19, 3 }, { "--nonews --nosplash --debug --nowebservicediscovery --props=test/jalview/bin/commandsTest.jvprops --argfile=test/jalview/bin/commandsTest2.argfile2 ", 16, 0, 2 }, + { "--nonews --nosplash --debug --nowebservicediscovery --props=test/jalview/bin/commandsTest.jvprops --open=./examples/test_fab41.result/sample.a2m " + + "--allstructures " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--structureviewer=none " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_2_model_4.pdb " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_3_model_2.pdb", + 16, 10, 0 }, + { "--nonews --nosplash --debug --nowebservicediscovery --props=test/jalview/bin/commandsTest.jvprops --open=./examples/test_fab41.result/sample.a2m " + + "--allstructures " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb " + + "--noallstructures " + "--structureviewer=none " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_2_model_4.pdb " + + "--structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_3_model_2.pdb", + 16, 10, 2 }, /* */ // diff --git a/test/jalview/bin/argparser/ArgParserTest.java b/test/jalview/bin/argparser/ArgParserTest.java index bc2be78..ca63e44 100644 --- a/test/jalview/bin/argparser/ArgParserTest.java +++ b/test/jalview/bin/argparser/ArgParserTest.java @@ -184,9 +184,12 @@ public class ArgParserTest @DataProvider(name = "argSubValsAndLinkedIds") public Object[][] argSubValsAndLinkedIds() { - return new Object[][] { { - "--debug --append=[hi]test/jalview/bin/argparser/testfiles/test1.fa", - "JALVIEW:0", Arg.APPEND, "hi", "true", true }, + return new Object[][] { + // + /* + */ + { "--debug --append=[hi]test/jalview/bin/argparser/testfiles/test1.fa", + "JALVIEW:0", Arg.APPEND, "hi", "true", true }, { "--append[linkedId1]=[new,hello=world,1]test/jalview/bin/argparser/testfiles/test1.fa --headless", "linkedId1", Arg.APPEND, "new", "true", true }, { "--append[linkedId2]=[new,hello=world,1]test/jalview/bin/argparser/testfiles/test1.fa --headless", @@ -198,7 +201,11 @@ public class ArgParserTest { "--append[linkedId5]=[new,hello=worlddomination,1]test/jalview/bin/argparser/testfiles/test1.fa --append[linkedId2]=[new;hello=world;1]test/jalview/bin/argparser/testfiles/test1.fa --headless", "linkedId5", Arg.APPEND, "hello", "world", false }, { "--append[linkedId6]=[new,hello=world,0]test/jalview/bin/argparser/testfiles/test1.fa --append[linkedId7]=[new;hello=world;1]test/jalview/bin/argparser/testfiles/test1.fa --headless", - "linkedId7", Arg.APPEND, "GETINDEX", "0", false }, }; + "linkedId7", Arg.APPEND, "GETINDEX", "0", false }, + /* + */ + // + }; } @DataProvider(name = "argAutoIndexAndSubstitutions") -- 1.7.10.2
argumentactionsub-value modifiers (optional)linked (optional)
‑‑structureimage filenameExport an image of a 3D structure opened in JMOL. Image formats can be: +
+ svg, +
+ png, +
+ eps. +
+ structureimagetype=name, + structureimagetextrenderer=name, + structureimagescale=number, + structureimagewidth=number, + structureimageheight=number +
‑‑structureimagetype nameSet the structure image format for the preceding --structureimage. Valid values are: +
+ svg, +
+ png, +
+ eps. +
‑‑backups / ‑‑nobackupsEnable (or disable) writing backup files when saving an ‑‑output file. This applies to the current open alignment -- to apply to all ‑‑output and ‑‑image files, use after ‑‑all.‑‑structureimagetextrenderer nameSets whether text in a vector structure image format (SVG, EPS) should be rendered as text or vector line-art. Possible values are: +
+ text, +
+ lineart. +
‑‑overwrite / ‑‑nooverwriteEnable (or disable) overwriting of output files without backups enabled. This applies to the current open alignment -- to apply to all ‑‑output and ‑‑image files, use after ‑‑all.‑‑structureimagescale numberSets a scaling for bitmap structure image format (PNG). Should be given as a floating point number. If used in conjunction with --structureimagewidth and --structureimageheight then the smallest scaling will be used (structureimagescale, structureimagewidth and structureimageheight provide bounds for the structure image). +
‑‑closeClose the current open alignment window. This occurs after other output arguments. This applies to the current open alignment -- to apply to all ‑‑output and ‑‑image files, use after ‑‑all.‑‑structureimagewidth numberSets a width for bitmap structure image format (PNG) with the height maintaining the aspect ratio. Should be given as a positive integer. If used in conjunction with --structureimagescale and --structureimageheight then the smallest scaling will be used (structureimagescale, structureimagewidth and structureimageheight provide bounds for the structure image). +
‑‑structureimageheight numberSets a height for bitmap structure image format (PNG) with the width maintaining the aspect ratio. Should be given as a positive integer. If used in conjunction with --structureimagescale and --structureimagewidth then the smallest scaling will be used (structureimagescale, structureimagewidth and structureimageheight provide bounds for the structure image). +
‑‑allstructures / ‑‑noallstructures + Apply (or stop applying) the following 3D structure formatting arguments to all structures within the current open alignment. Whilst --allstructures will continue to operate for a --new alignment, the structure formatting arguments must be set again for each new alignment. +
‑‑quit After all files have been opened, appended and output, quit Jalview. In ‑‑headless mode this already happens.