From 58b30fcf2ee02b59666655a5bdf99d6e660b2e70 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 31 Jan 2019 16:42:28 +0000 Subject: [PATCH] JAL-3190 rough Proof of Concept of JalviewJS - Chimera --- src/ext/edu/ucsf/rbvi/strucviz2/ChimUtils.java | 6 +- .../edu/ucsf/rbvi/strucviz2/ChimeraManager.java | 98 ++++++++++++++++++-- src/ext/edu/ucsf/rbvi/strucviz2/Logger.java | 27 ++++++ .../edu/ucsf/rbvi/strucviz2/StructureManager.java | 9 +- .../ucsf/rbvi/strucviz2/port/ListenerThreads.java | 12 ++- .../ext/rbvi/chimera/JalviewChimeraBinding.java | 3 +- src/jalview/gui/ChimeraViewFrame.java | 5 +- src/jalview/gui/Preferences.java | 2 +- src/jalview/jbgui/GPreferences.java | 4 +- 9 files changed, 140 insertions(+), 26 deletions(-) create mode 100644 src/ext/edu/ucsf/rbvi/strucviz2/Logger.java diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/ChimUtils.java b/src/ext/edu/ucsf/rbvi/strucviz2/ChimUtils.java index 1d57a31..819c83a 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/ChimUtils.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/ChimUtils.java @@ -38,15 +38,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType; public abstract class ChimUtils { - private static Logger logger = LoggerFactory.getLogger(ChimUtils.class); + private static Logger logger = new Logger();//LoggerFactory.getLogger(ChimUtils.class); static int MAX_SUB_MODELS = 1000; diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java index a910a5a..d23f41a 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java @@ -32,6 +32,7 @@ */ package ext.edu.ucsf.rbvi.strucviz2; +import jalview.util.Platform; import jalview.ws.HttpClientUtils; import java.awt.Color; @@ -40,6 +41,9 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; @@ -47,10 +51,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.ws.rs.HttpMethod; + import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType; import ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads; @@ -66,6 +72,12 @@ public class ChimeraManager private static final boolean debug = false; + /* + * this has to be set to the port number of the REST server + * currently being run by Chimera + */ + private int jsPortNo = 51940; + private int chimeraRestPort; private Process chimera; @@ -74,8 +86,8 @@ public class ChimeraManager private Map currentModelsMap; - private Logger logger = LoggerFactory - .getLogger(ext.edu.ucsf.rbvi.strucviz2.ChimeraManager.class); + private Logger logger = new Logger(); + //LoggerFactory.getLogger(ext.edu.ucsf.rbvi.strucviz2.ChimeraManager.class); private StructureManager structureManager; @@ -213,26 +225,28 @@ public class ChimeraManager public List openModel(String modelPath, String modelName, ModelType type) { - logger.info("chimera open " + modelPath); + String toOpen = Platform.isJS() ? "cifID:" + modelName : modelPath; + + logger.info("chimera open " + toOpen); // stopListening(); List modelList = getModelList(); List response = null; // TODO: [Optional] Handle modbase models if (type == ModelType.MODBASE_MODEL) { - response = sendChimeraCommand("open modbase:" + modelPath, true); + response = sendChimeraCommand("open modbase:" + toOpen, true); // } else if (type == ModelType.SMILES) { // response = sendChimeraCommand("open smiles:" + modelName, true); // modelName = "smiles:" + modelName; } else { - response = sendChimeraCommand("open " + modelPath, true); + response = sendChimeraCommand("open " + toOpen, true); } if (response == null) { // something went wrong - logger.warn("Could not open " + modelPath); + logger.warn("Could not open " + toOpen); return null; } @@ -475,6 +489,10 @@ public class ChimeraManager List modelList = new ArrayList<>(); List list = sendChimeraCommand("list models type molecule", true); + if (Platform.isJS()) + { + list.add("model id #0 type Molecule name foo"); + } if (list != null) { for (String modelLine : list) @@ -513,6 +531,11 @@ public class ChimeraManager public boolean isChimeraLaunched() { + if (Platform.isJS()) + { + this.chimeraRestPort = jsPortNo; + return true; + } boolean launched = false; if (chimera != null) { @@ -539,12 +562,19 @@ public class ChimeraManager */ public boolean launchChimera(List chimeraPaths) { + if (Platform.isJS()) + { + // Chimera: run Utilities | REST server + // and read port number off reply log, set as jsPortNo + this.chimeraRestPort = jsPortNo; + return true; + } // Do nothing if Chimera is already launched if (isChimeraLaunched()) { return true; } - + // Try to launch Chimera (eventually using one of the possible paths) String error = "Error message: "; String workingPath = ""; @@ -820,6 +850,11 @@ public class ChimeraManager */ protected List sendRestCommand(String command) { + if (Platform.isJS()) + { + return sendRestCommandForJS(command); + } + String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run"; List commands = new ArrayList<>(1); commands.add(new BasicNameValuePair("command", command)); @@ -854,6 +889,51 @@ public class ChimeraManager } /** + * Alternative that uses java.net not apache http client + * @param command + * @return + */ + protected List sendRestCommandForJS(String command) + { + List reply = new ArrayList<>(); + BufferedReader response = null; + try + { + String encoded = URLEncoder.encode(command, "UTF-8"); + URL url = new URL("http://127.0.0.1:" + this.chimeraRestPort + "/run?command="+encoded); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET); + connection.setDoInput(true); + InputStream is = connection.getInputStream(); + // JalviewJS can't read response without access-control-allow-origin * header + if (!Platform.isJS()) + { + response = new BufferedReader(new InputStreamReader(is, "UTF-8")); + String line = ""; + while ((line = response.readLine()) != null) + { + reply.add(line); + } + } + } catch (Exception e) + { + logger.error("REST call '" + command + "' failed: " + e.getMessage()); + } finally + { + if (response != null) + { + try + { + response.close(); + } catch (IOException e) + { + } + } + } + return reply; + } + + /** * Send a command to stdin of Chimera process, and optionally read any * responses. * diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/Logger.java b/src/ext/edu/ucsf/rbvi/strucviz2/Logger.java new file mode 100644 index 0000000..8c56064 --- /dev/null +++ b/src/ext/edu/ucsf/rbvi/strucviz2/Logger.java @@ -0,0 +1,27 @@ +package ext.edu.ucsf.rbvi.strucviz2; + +import java.io.IOException; + +public class Logger { + + public void error(String string, IOException ioe) { + System.out.println("Error: " + string + " " + ioe.toString()); + } + + public void warn(String string, Exception ex) { + System.out.println("Warn: " + string + " " + ex.toString()); + } + + public void info(String string) { + System.out.println("Info: " + string); + } + + public void warn(String string) { + System.out.println("Warn: " + string); + } + + public void error(String string) { + System.out.println("Error: " + string ); + } + +} diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java b/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java index 09a9713..b71f6fa 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java @@ -46,8 +46,8 @@ import java.util.Map; import java.util.Properties; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; /** * This object maintains the relationship between Chimera objects and Cytoscape @@ -89,8 +89,9 @@ public class StructureManager private File configurationDirectory = null; - private static Logger logger = LoggerFactory - .getLogger(ext.edu.ucsf.rbvi.strucviz2.StructureManager.class); + private static Logger logger = new Logger(); +// = LoggerFactory +// .getLogger(ext.edu.ucsf.rbvi.strucviz2.StructureManager.class); public StructureManager(boolean haveGUI) { diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java b/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java index 379097c..b08a919 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java @@ -41,8 +41,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import ext.edu.ucsf.rbvi.strucviz2.Logger; + +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; import ext.edu.ucsf.rbvi.strucviz2.StructureManager; @@ -61,7 +63,7 @@ public class ListenerThreads extends Thread private Map> replyLog = null; - private Logger logger; + private Logger logger = new Logger(); private StructureManager structureManager = null; @@ -83,8 +85,8 @@ public class ListenerThreads extends Thread // Get a line-oriented reader InputStream readChan = chimera.getInputStream(); lineReader = new BufferedReader(new InputStreamReader(readChan)); - logger = LoggerFactory - .getLogger(ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads.class); + logger =new Logger(); + //LoggerFactory.getLogger(ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads.class); } /** diff --git a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index 00446f2..12f3752 100644 --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@ -40,6 +40,7 @@ import jalview.structure.StructureMappingcommandSet; import jalview.structure.StructureSelectionManager; import jalview.structures.models.AAStructureBindingModel; import jalview.util.MessageManager; +import jalview.util.Platform; import java.awt.Color; import java.io.File; @@ -599,7 +600,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel boolean launched = viewer .launchChimera(StructureManager.getChimeraPaths()); - if (launched) + if (launched && !Platform.isJS()) { startChimeraProcessMonitor(); } diff --git a/src/jalview/gui/ChimeraViewFrame.java b/src/jalview/gui/ChimeraViewFrame.java index 9167c00..8392606 100644 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@ -354,7 +354,10 @@ public class ChimeraViewFrame extends StructureViewerBase } } - jmb.startChimeraListener(); + if (!Platform.isJS()) + { + jmb.startChimeraListener(); + } } /** diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index 35641f8..5b84594 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -1200,7 +1200,7 @@ public class Preferences extends GPreferences @Override protected void structureViewer_actionPerformed(String selectedItem) { - if (!selectedItem.equals(ViewerType.CHIMERA.name())) + if (!selectedItem.equals(ViewerType.CHIMERA.name()) || Platform.isJS()) { return; } diff --git a/src/jalview/jbgui/GPreferences.java b/src/jalview/jbgui/GPreferences.java index 1e01cc3..94698b9 100755 --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@ -1293,8 +1293,8 @@ public class GPreferences extends JPanel { pathLabel.setVisible(false); chimeraPath.setVisible(false); - viewerLabel.setVisible(false); - structViewer.setVisible(false); +// viewerLabel.setVisible(false); +// structViewer.setVisible(false); } return structureTab; -- 1.7.10.2