From 01f8ff469a507604ed961418f7c80f9b245e60ca Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Fri, 3 Feb 2023 21:10:51 +0000 Subject: [PATCH] JAL-629 Fasta sequence id reading whitespace fix. Flexioble pae json keys and structure. Headless fixes. Logging fixes (MessageManager -- test broken). ArgParser and Console helper methods. Commands added e.g. --colour=gecos:flower. --- src/jalview/bin/ArgParser.java | 7 ++ src/jalview/bin/Commands.java | 120 ++++++++++++-------- src/jalview/bin/Console.java | 23 +++- src/jalview/bin/Jalview.java | 56 +++++---- src/jalview/gui/AlignFrame.java | 3 +- src/jalview/gui/StructureChooser.java | 4 +- src/jalview/io/AlignFile.java | 3 +- src/jalview/log/JLogger.java | 2 +- src/jalview/util/MapUtils.java | 43 +++++++ src/jalview/util/MessageManager.java | 15 +-- src/jalview/util/StringUtils.java | 16 ++- .../ws/datamodel/alphafold/PAEContactMatrix.java | 16 +-- src/jalview/ws/dbsources/EBIAlfaFold.java | 25 +++- 13 files changed, 234 insertions(+), 99 deletions(-) create mode 100644 src/jalview/util/MapUtils.java diff --git a/src/jalview/bin/ArgParser.java b/src/jalview/bin/ArgParser.java index bb88536..338d130 100644 --- a/src/jalview/bin/ArgParser.java +++ b/src/jalview/bin/ArgParser.java @@ -687,6 +687,13 @@ public class ArgParser return (vals == null || vals.size() == 0) ? null : vals.get(0); } + public static boolean hasValue(Map m, Arg a) + { + if (!m.containsKey(a)) + return false; + return getValue(m, a) != null; + } + public static boolean getBoolean(Map m, Arg a) { ArgValues av = getArgValues(m, a); diff --git a/src/jalview/bin/Commands.java b/src/jalview/bin/Commands.java index 2d7f02b..faf2c9c 100644 --- a/src/jalview/bin/Commands.java +++ b/src/jalview/bin/Commands.java @@ -1,6 +1,7 @@ package jalview.bin; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -64,7 +65,6 @@ public class Commands { for (String id : argParser.linkedIds()) { - Console.debug("##### id=" + id); Commands cmds = new Commands(); if (id == null) { @@ -258,6 +258,13 @@ public class Commands af.getCurrentView().setWrapAlignment(true); } + // colour aligment? + if (ArgParser.hasValue(m, Arg.COLOUR)) + { + af.changeColour_actionPerformed( + ArgParser.getValue(m, Arg.COLOUR)); + } + // change alignment frame title if (ArgParser.getValue(m, Arg.TITLE) != null) af.setTitle(ArgParser.getValue(m, Arg.TITLE)); @@ -329,8 +336,7 @@ public class Commands af.getCurrentView().addFile(new File(openFile), format); } - System.out - .println("Command " + Arg.OPEN + " executed successfully!"); + Console.debug("Command " + Arg.OPEN + " executed successfully!"); } if (first) // first=true means nothing opened @@ -350,53 +356,6 @@ public class Commands } - // load a pAE file if given - if (ArgParser.getValues(m, Arg.PAEMATRIX) != null) - { - AlignFrame af = afMap.get(id); - if (af != null) - { - for (String val : ArgParser.getValues(m, Arg.PAEMATRIX)) - { - SubVal subVal = ArgParser.getSubVal(val); - File paeFile = new File(subVal.content); - String structId = "structid".equals(subVal.keyName) - ? subVal.keyValue - : null; - if (subVal.notSet()) - { - // take structid from pdbfilename - } - if ("structfile".equals(subVal.keyName)) - { - EBIAlfaFold.addAlphaFoldPAEToStructure( - af.getCurrentView().getAlignment(), paeFile, - subVal.index, subVal.keyValue, false); - } - else if ("structid".equals(subVal.keyName)) - { - EBIAlfaFold.addAlphaFoldPAEToStructure( - af.getCurrentView().getAlignment(), paeFile, - subVal.index, subVal.keyValue, true); - } - else - { - EBIAlfaFold.addAlphaFoldPAEToSequence( - af.getCurrentView().getAlignment(), paeFile, - subVal.index, - "seqid".equals(subVal.keyName) ? subVal.keyValue - : null); - // required to readjust the height and position of the pAE - // annotation - } - for (AlignmentViewPanel ap : af.getAlignPanels()) - { - ap.adjustAnnotationHeight(); - } - } - } - } - // open the structure (from same PDB file or given PDBfile) if (!ArgParser.getBoolean(m, Arg.NOSTRUCTURE)) { @@ -456,6 +415,67 @@ public class Commands } } + // load a pAE file if given + if (ArgParser.getValues(m, Arg.PAEMATRIX) != null) + { + AlignFrame af = afMap.get(id); + if (af != null) + { + for (String val : ArgParser.getValues(m, Arg.PAEMATRIX)) + { + SubVal subVal = ArgParser.getSubVal(val); + File paeFile = new File(subVal.content); + String paePath = null; + try + { + paePath = paeFile.getCanonicalPath(); + } catch (IOException e) + { + paePath = paeFile.getAbsolutePath(); + Console.warn( + "Problem with the PAE file path: '" + paePath + "'"); + } + String structId = "structid".equals(subVal.keyName) + ? subVal.keyValue + : null; + if (subVal.notSet()) + { + // take structid from pdbfilename + } + if ("structfile".equals(subVal.keyName)) + { + Console.info("***** Attaching paeFile '" + paePath + "' to " + + subVal.keyName + "=" + subVal.keyValue); + EBIAlfaFold.addAlphaFoldPAEToStructure( + af.getCurrentView().getAlignment(), paeFile, + subVal.index, subVal.keyValue, false); + } + else if ("structid".equals(subVal.keyName)) + { + Console.info("***** Attaching paeFile '" + paePath + "' to " + + subVal.keyName + "=" + subVal.keyValue); + EBIAlfaFold.addAlphaFoldPAEToStructure( + af.getCurrentView().getAlignment(), paeFile, + subVal.index, subVal.keyValue, true); + } + else + { + Console.debug("***** Attaching paeFile '" + paePath + + "' to sequence index " + subVal.index); + EBIAlfaFold.addAlphaFoldPAEToSequence( + af.getCurrentView().getAlignment(), paeFile, + subVal.index, null); + // required to readjust the height and position of the pAE + // annotation + } + for (AlignmentViewPanel ap : af.getAlignPanels()) + { + ap.adjustAnnotationHeight(); + } + } + } + } + boolean doShading = ArgParser.getBoolean(m, Arg.TEMPFAC_SHADING); if (doShading) { diff --git a/src/jalview/bin/Console.java b/src/jalview/bin/Console.java index 3e09d07..b85a4d2 100644 --- a/src/jalview/bin/Console.java +++ b/src/jalview/bin/Console.java @@ -20,7 +20,10 @@ */ package jalview.bin; +import java.util.Locale; + import jalview.log.JLogger; +import jalview.log.JLoggerI; import jalview.log.JLoggerI.LogLevel; import jalview.log.JLoggerLog4j; import jalview.util.ChannelProperties; @@ -241,7 +244,7 @@ public class Console // Test message if (log != null) { - // Logging test message should got through the logger object + // Logging test message should go through the logger object if (log.loggerExists()) log.debug(Console.LOGGING_TEST_MESSAGE); // Tell the user that debug is enabled @@ -255,6 +258,24 @@ public class Console } } + public static void setLogLevel(String logLevelString) + { + for (LogLevel logLevel : JLoggerI.LogLevel.values()) + { + if (logLevel.toString().toLowerCase(Locale.ROOT) + .equals(logLevelString.toLowerCase(Locale.ROOT))) + { + log.setLevel(logLevel); + if (!Platform.isJS()) + { + Log4j.init(logLevel); + } + JLoggerLog4j.getLogger("org.apache.axis", logLevel); + break; + } + } + } + public final static String LOGGING_TEST_MESSAGE = "Logging to STDERR"; } diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index 6238c7d..e259cc2 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -301,10 +301,19 @@ public class Jalview // old ArgsParser ArgsParser aparser = new ArgsParser(args); - // new ArgParser - ArgParser argparser = new ArgParser(args); boolean headless = false; + try + { + Console.initLogger(); + } catch (NoClassDefFoundError error) + { + error.printStackTrace(); + System.out.println("\nEssential logging libraries not found." + + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview"); + System.exit(0); + } + String usrPropsFile = aparser.getValue("props"); Cache.loadProperties(usrPropsFile); // must do this before if (usrPropsFile != null) @@ -313,6 +322,31 @@ public class Jalview "CMD [-props " + usrPropsFile + "] executed successfully!"); } + // set log level from cache properties + Console.setLogLevel(Cache.getDefault(Cache.JALVIEWLOGLEVEL, "INFO")); + + // new ArgParser + ArgParser argparser = new ArgParser(args); // do this after + // Console.initLogger, but TODO + // want --props before then + // CATCH22 + + if (argparser.isSet(Arg.HEADLESS)) + headless = argparser.getBool(Arg.HEADLESS); + boolean commandsSuccess = Commands.processArgs(argparser, headless); + if (commandsSuccess) + { + Console.info("Successfully completed commands"); + if (headless) + System.exit(0); + } + else + { + Console.warn("Error when running commands"); + if (headless) + System.exit(1); + } + if (!Platform.isJS()) /** * Java only @@ -386,17 +420,6 @@ public class Jalview System.setProperty("http.agent", "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown")); - try - { - Console.initLogger(); - } catch (NoClassDefFoundError error) - { - error.printStackTrace(); - System.out.println("\nEssential logging libraries not found." - + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview"); - System.exit(0); - } - desktop = null; setLookAndFeel(); @@ -563,13 +586,6 @@ public class Jalview }.start(); } - if (argparser.isSet(Arg.HEADLESS)) - headless = argparser.getBool(Arg.HEADLESS); - if (Commands.processArgs(argparser, headless)) - { - System.exit(1); - } - String file = null, data = null; FileFormatI format = null; DataSourceType protocol = null; diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 032b0bb..f9381b4 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -977,7 +977,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, @Override public void setProgressBar(String message, long id) { - progressBar.setProgressBar(message, id); + if (!Platform.isHeadless()) + progressBar.setProgressBar(message, id); } @Override diff --git a/src/jalview/gui/StructureChooser.java b/src/jalview/gui/StructureChooser.java index d38f39f..30b3c06 100644 --- a/src/jalview/gui/StructureChooser.java +++ b/src/jalview/gui/StructureChooser.java @@ -65,6 +65,7 @@ import jalview.jbgui.GStructureChooser; import jalview.structure.StructureMapping; import jalview.structure.StructureSelectionManager; import jalview.util.MessageManager; +import jalview.util.Platform; import jalview.ws.DBRefFetcher; import jalview.ws.DBRefFetcher.FetchFinishedListenerI; import jalview.ws.seqfetcher.DbSourceProxy; @@ -1534,7 +1535,8 @@ public class StructureChooser extends GStructureChooser @Override public void setProgressBar(String message, long id) { - progressBar.setProgressBar(message, id); + if (!Platform.isHeadless()) + progressBar.setProgressBar(message, id); } @Override diff --git a/src/jalview/io/AlignFile.java b/src/jalview/io/AlignFile.java index 3202ac9..1233940 100755 --- a/src/jalview/io/AlignFile.java +++ b/src/jalview/io/AlignFile.java @@ -33,6 +33,7 @@ import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.util.MessageManager; +import jalview.util.StringUtils; /** * DOCUMENT ME! @@ -378,7 +379,7 @@ public abstract class AlignFile extends FileParse { Sequence seq = null; id = id.trim(); - int space = id.indexOf(" "); + int space = StringUtils.indexOfFirstWhitespace(id); if (space > -1) { seq = new Sequence(id.substring(0, space), ""); diff --git a/src/jalview/log/JLogger.java b/src/jalview/log/JLogger.java index 45dde90..f9859f5 100644 --- a/src/jalview/log/JLogger.java +++ b/src/jalview/log/JLogger.java @@ -60,7 +60,7 @@ public abstract class JLogger implements JLoggerI public static JLogger getLogger(Class c) { - return getLogger(c); + return getLogger(c, LogLevel.INFO); } public static JLogger getLogger(Class c, LogLevel loglevel) diff --git a/src/jalview/util/MapUtils.java b/src/jalview/util/MapUtils.java new file mode 100644 index 0000000..e0d9c0b --- /dev/null +++ b/src/jalview/util/MapUtils.java @@ -0,0 +1,43 @@ +package jalview.util; + +import java.util.Map; + +public class MapUtils +{ + /* + * Return the value of the first key that exists in the map + */ + public static V getFirst(Map map, K... keys) + { + return getFirst(false, map, keys); + } + + public static V getFirst(boolean nonNull, Map map, K... keys) + { + for (K key : keys) + { + if (map.containsKey(key)) + { + if (!(nonNull && (map.get(key) == null))) + { + return map.get(key); + } + else if (!nonNull) + { + return map.get(key); + } + } + } + return null; + } + + public static boolean containsAKey(Map map, K... keys) + { + for (K key : keys) + { + if (map.containsKey(key)) + return true; + } + return false; + } +} diff --git a/src/jalview/util/MessageManager.java b/src/jalview/util/MessageManager.java index acd4591..e55bfab 100644 --- a/src/jalview/util/MessageManager.java +++ b/src/jalview/util/MessageManager.java @@ -27,7 +27,7 @@ import java.util.ResourceBundle; import java.util.ResourceBundle.Control; import java.util.Set; -import jalview.log.JLoggerLog4j; +import jalview.bin.Console; /** * @@ -40,9 +40,6 @@ public class MessageManager { private static ResourceBundle rb; - private static JLoggerLog4j log = JLoggerLog4j - .getLogger(MessageManager.class.getCanonicalName()); - private static Locale loc; private static Set reportedMissing = new HashSet<>(); @@ -55,7 +52,7 @@ public class MessageManager loc = Locale.getDefault(); // Locale.setDefault(loc); /* Getting messages for GV */ - log.info("Getting messages for lang: " + loc); + Console.info("Getting messages for lang: " + loc); Control control = Control.getControl(Control.FORMAT_PROPERTIES); rb = ResourceBundle.getBundle("lang.Messages", loc, control); // if (log.isLoggable(Level.FINEST)) @@ -65,12 +62,12 @@ public class MessageManager // } } catch (Exception q) { - log.warn("Exception when initting Locale for i18n messages\n" + Console.warn("Exception when initting Locale for i18n messages\n" + q.getMessage()); q.printStackTrace(); } catch (Error v) { - log.warn("Error when initting Locale for i18n messages\n" + Console.warn("Error when initting Locale for i18n messages\n" + v.getMessage()); v.printStackTrace(); } @@ -119,7 +116,7 @@ public class MessageManager return MessageFormat.format(rb.getString(key), params); } catch (Exception e) { - log.warn("I18N missing: " + loc + "\t" + key); + Console.warn("I18N missing: " + loc + "\t" + key); } String value = "[missing key] " + key + ""; for (Object p : params) @@ -186,7 +183,7 @@ public class MessageManager if (!reportedMissing.contains(key)) { reportedMissing.add(key); - log.info(msg); + Console.info(msg); } } } diff --git a/src/jalview/util/StringUtils.java b/src/jalview/util/StringUtils.java index 8b62e48..adba947 100644 --- a/src/jalview/util/StringUtils.java +++ b/src/jalview/util/StringUtils.java @@ -20,12 +20,12 @@ */ package jalview.util; -import java.util.Locale; - import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; import java.util.regex.Pattern; public class StringUtils @@ -585,4 +585,16 @@ public class StringUtils } return min < text.length() + 1 ? min : -1; } + + public static int indexOfFirstWhitespace(String text) + { + int index = -1; + Pattern pat = Pattern.compile("\\s"); + Matcher m = pat.matcher(text); + if (m.find()) + { + index = m.start(); + } + return index; + } } diff --git a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java index 3298a96..272d21d 100644 --- a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java +++ b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java @@ -9,6 +9,7 @@ import jalview.datamodel.ContactListImpl; import jalview.datamodel.ContactListProviderI; import jalview.datamodel.ContactMatrixI; import jalview.datamodel.SequenceI; +import jalview.util.MapUtils; public class PAEContactMatrix implements ContactMatrixI { @@ -39,7 +40,7 @@ public class PAEContactMatrix implements ContactMatrixI // convert the lists to primitive arrays and store length = _refSeq.getEnd() - _refSeq.getStart() + 1; - if (!pae_obj.containsKey("predicted_aligned_error")) + if (!MapUtils.containsAKey(pae_obj, "predicted_aligned_error", "pae")) { parse_version_1_pAE(pae_obj); return; @@ -59,10 +60,11 @@ public class PAEContactMatrix implements ContactMatrixI { elements = new float[length][length]; // this is never going to be reached by the integer rounding.. or is it ? - maxscore = ((Double) pae_obj.get("max_predicted_aligned_error")) - .floatValue(); - Iterator> scoreRows = ((List>) pae_obj - .get("predicted_aligned_error")).iterator(); + maxscore = ((Double) MapUtils.getFirst(pae_obj, + "max_predicted_aligned_error", "max_pae")).floatValue(); + Iterator> scoreRows = ((List>) MapUtils + .getFirst(pae_obj, "predicted_aligned_error", "pae")) + .iterator(); int row = 0, col = 0; while (scoreRows.hasNext()) { @@ -110,8 +112,8 @@ public class PAEContactMatrix implements ContactMatrixI elements[row - 1][col - 1] = escore; } - maxscore = ((Double) pae_obj.get("max_predicted_aligned_error")) - .floatValue(); + maxscore = ((Double) MapUtils.getFirst(pae_obj, + "max_predicted_aligned_error", "max_pae")).floatValue(); } @Override diff --git a/src/jalview/ws/dbsources/EBIAlfaFold.java b/src/jalview/ws/dbsources/EBIAlfaFold.java index e5f1243..b3bcfd9 100644 --- a/src/jalview/ws/dbsources/EBIAlfaFold.java +++ b/src/jalview/ws/dbsources/EBIAlfaFold.java @@ -30,6 +30,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; import org.json.simple.parser.ParseException; import com.stevesoft.pat.Regex; @@ -375,7 +377,6 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy for (int i = 0; i < seqs.length; i++) { SequenceI s = seqs[i]; - Console.debug("******* sequences[" + i + "]='" + s.getName() + "'"); } } /* end debug */ @@ -388,8 +389,6 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy } if (sequence == null) { - Console.debug("***** Looking for sequence with id '" + seqId + "'"); - SequenceI[] sequences = pdbAlignment.findSequenceMatch(seqId); if (sequences == null || sequences.length < 1) { @@ -403,17 +402,31 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy } } - List pae_obj = (List) Platform.parseJSON(pae_input); - if (pae_obj == null) + Object paeJson = Platform.parseJSON(pae_input); + JSONObject paeDict = null; + if (paeJson instanceof JSONObject) + { + Console.debug("***** paeJson is a JSONObject"); + paeDict = (JSONObject) paeJson; + } + else if (paeJson instanceof JSONArray) + { + JSONArray jsonArray = (JSONArray) paeJson; + if (jsonArray.size() > 0) + paeDict = (JSONObject) jsonArray.get(0); + } + + if (paeDict == null) { Console.debug("JSON file did not parse properly."); return false; } ContactMatrixI matrix = new PAEContactMatrix(sequence, - (Map) pae_obj.get(0)); + (Map) paeDict); AlignmentAnnotation cmannot = sequence.addContactList(matrix); pdbAlignment.addAnnotation(cmannot); + return true; } -- 1.7.10.2