+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions, and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Redistributions must acknowledge that this software was
+ * originally developed by the UCSF Computer Graphics Laboratory
+ * under support by the NIH National Center for Research Resources,
+ * grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
package ext.edu.ucsf.rbvi.strucviz2;
import jalview.ws.HttpClientUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
this.structureManager = structureManager;
chimera = null;
chimeraListenerThread = null;
- currentModelsMap = new HashMap<Integer, ChimeraModel>();
+ currentModelsMap = new HashMap<>();
}
public List<ChimeraModel> getChimeraModels(String modelName,
ModelType modelType)
{
- List<ChimeraModel> models = new ArrayList<ChimeraModel>();
+ List<ChimeraModel> models = new ArrayList<>();
for (ChimeraModel model : currentModelsMap.values())
{
if (modelName.equals(model.getModelName())
public Map<String, List<ChimeraModel>> getChimeraModelsMap()
{
- Map<String, List<ChimeraModel>> models = new HashMap<String, List<ChimeraModel>>();
+ Map<String, List<ChimeraModel>> models = new HashMap<>();
for (ChimeraModel model : currentModelsMap.values())
{
String modelName = model.getModelName();
for (ChimeraModel chimeraModel : modelList)
{
// get model color
- Color modelColor = getModelColor(chimeraModel);
+ Color modelColor = isChimeraX() ? null : getModelColor(chimeraModel);
if (modelColor != null)
{
chimeraModel.setModelColor(modelColor);
// chimeraSend("repr stick "+newModel.toSpec());
// Create the information we need for the navigator
- if (type != ModelType.SMILES)
+ if (type != ModelType.SMILES && !isChimeraX())
{
addResidues(chimeraModel);
}
public void stopListening()
{
- sendChimeraCommand("listen stop models ; listen stop selection ", false);
+ // TODO send this command when viewer connection is closed in Jalview
+ String command = isChimeraX
+ ? "info notify stop models jalview; info notify stop selection jalview"
+ : "listen stop models ; listen stop selection ";
+ sendChimeraCommand(command, false);
}
/**
*/
public void startListening(String uri)
{
- sendChimeraCommand("listen start models url " + uri
- + ";listen start select prefix SelectionChanged url " + uri,
- false);
+ String command = isChimeraX
+ ? ("info notify start models prefix ModelChanged jalview url "
+ + uri
+ + "; info notify start selection jalview prefix SelectionChanged url "
+ + uri)
+ : ("listen start models url " + uri
+ + ";listen start select prefix SelectionChanged url "
+ + uri);
+ sendChimeraCommand(command, false);
}
/**
sendChimeraCommand("stop really", false);
try
{
+ // TODO is this too violent? could it force close the process
+ // before it has done an orderly shutdown?
chimera.destroy();
} catch (Exception ex)
{
public Map<Integer, ChimeraModel> getSelectedModels()
{
- Map<Integer, ChimeraModel> selectedModelsMap = new HashMap<Integer, ChimeraModel>();
+ Map<Integer, ChimeraModel> selectedModelsMap = new HashMap<>();
List<String> chimeraReply = sendChimeraCommand(
"list selection level molecule", true);
if (chimeraReply != null)
*/
public List<String> getSelectedResidueSpecs()
{
- List<String> selectedResidues = new ArrayList<String>();
- List<String> chimeraReply = sendChimeraCommand(
- "list selection level residue", true);
+ List<String> selectedResidues = new ArrayList<>();
+
+ /*
+ * skip for now if ChimeraX - times out
+ */
+ if (isChimeraX)
+ {
+ return selectedResidues;
+ }
+
+ // in fact 'listinfo' (undocumented) works in ChimeraX
+ String command = (isChimeraX ? "info" : "list")
+ + " selection level residue";
+ List<String> chimeraReply = sendChimeraCommand(command, true);
if (chimeraReply != null)
{
/*
- * expect 0, 1 or more lines of the format
+ * expect 0, 1 or more lines of the format either
+ * Chimera:
* residue id #0:43.A type GLY
- * where we are only interested in the atomspec #0.43.A
+ * ChimeraX:
+ * residue id /A:89 name THR index 88
+ * We are only interested in the atomspec (third token of the reply)
*/
for (String inputLine : chimeraReply)
{
String[] inputLineParts = inputLine.split("\\s+");
- if (inputLineParts.length == 5)
+ if (inputLineParts.length >= 5)
{
selectedResidues.add(inputLineParts[2]);
}
// TODO: [Optional] Handle smiles names in a better way in Chimera?
public List<ChimeraModel> getModelList()
{
- List<ChimeraModel> modelList = new ArrayList<ChimeraModel>();
- List<String> list = sendChimeraCommand("list models type molecule",
- true);
- if (list != null)
- {
- for (String modelLine : list)
- {
- ChimeraModel chimeraModel = new ChimeraModel(modelLine);
- modelList.add(chimeraModel);
- }
- }
- return modelList;
+ List<ChimeraModel> modelList = new ArrayList<>();
+ modelList.add(new ChimeraModel("4zhp", ModelType.PDB_MODEL, 1, 0));
+ return modelList; // ChimeraX doesn't have 'list models' command
+ // List<String> list = sendChimeraCommand("list models type molecule",
+ // true);
+ // if (list != null)
+ // {
+ // for (String modelLine : list)
+ // {
+ // ChimeraModel chimeraModel = new ChimeraModel(modelLine);
+ // modelList.add(chimeraModel);
+ // }
+ // }
+ // return modelList;
}
/**
*/
public List<String> getPresets()
{
- ArrayList<String> presetList = new ArrayList<String>();
+ ArrayList<String> presetList = new ArrayList<>();
List<String> output = sendChimeraCommand("preset list", true);
if (output != null)
{
// iterate over possible paths for starting Chimera
for (String chimeraPath : chimeraPaths)
{
- File path = new File(chimeraPath);
- // uncomment the next line to simulate Chimera not installed
- // path = new File(chimeraPath + "x");
- if (!path.canExecute())
- {
- error += "File '" + path + "' does not exist.\n";
- continue;
- }
try
{
- List<String> args = new ArrayList<String>();
+ // ensure symbolic links are resolved
+ chimeraPath = Paths.get(chimeraPath).toRealPath().toString();
+ isChimeraX = chimeraPath.toLowerCase().contains("chimerax");
+ File path = new File(chimeraPath);
+ // uncomment the next line to simulate Chimera not installed
+ // path = new File(chimeraPath + "x");
+ if (!path.canExecute())
+ {
+ error += "File '" + path + "' does not exist.\n";
+ continue;
+ }
+ List<String> args = new ArrayList<>();
args.add(chimeraPath);
// shows Chimera output window but suppresses REST responses:
// args.add("--debug");
- args.add("--start");
- args.add("RESTServer");
+ if (isChimeraX())
+ {
+ args.add("--cmd");
+ args.add("remote rest start");
+ }
+ else
+ {
+ args.add("--start");
+ args.add("RESTServer");
+ }
ProcessBuilder pb = new ProcessBuilder(args);
chimera = pb.start();
error = "";
break;
} catch (Exception e)
{
- // Chimera could not be started
+ // Chimera could not be started using this path
error += e.getMessage();
}
}
{
responses.append("\n" + response);
// expect: REST server on host 127.0.0.1 port port_number
+ // ChimeraX is the same except "REST server started on host..."
if (response.startsWith("REST server"))
{
String[] tokens = response.split(" ");
- if (tokens.length == 7 && "port".equals(tokens[5]))
+ for (int i = 0; i < tokens.length - 1; i++)
{
- port = Integer.parseInt(tokens[6]);
- break;
+ if ("port".equals(tokens[i]))
+ {
+ port = Integer.parseInt(tokens[i + 1]);
+ break;
+ }
}
}
+ if (port > 0)
+ {
+ break; // hack for hanging readLine()
+ }
response = lineReader.readLine();
}
} catch (Exception e)
public List<String> getAttrList()
{
- List<String> attributes = new ArrayList<String>();
- final List<String> reply = sendChimeraCommand("list resattr", true);
+ List<String> attributes = new ArrayList<>();
+ String command = (isChimeraX ? "info " : "list") + "resattr";
+ final List<String> reply = sendChimeraCommand(command, true);
if (reply != null)
{
for (String inputLine : reply)
public Map<ChimeraResidue, Object> getAttrValues(String aCommand,
ChimeraModel model)
{
- Map<ChimeraResidue, Object> values = new HashMap<ChimeraResidue, Object>();
+ Map<ChimeraResidue, Object> values = new HashMap<>();
final List<String> reply = sendChimeraCommand("list residue spec "
+ model.toSpec() + " attribute " + aCommand, true);
if (reply != null)
private volatile boolean busy = false;
+ private boolean isChimeraX;
+
/**
* Send a command to Chimera.
*
*/
public List<String> sendChimeraCommand(String command, boolean reply)
{
- // System.out.println("chimeradebug>> " + command);
+ System.out.println("chimeradebug>> " + command);
if (!isChimeraLaunched() || command == null
|| "".equals(command.trim()))
{
protected List<String> sendRestCommand(String command)
{
String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run";
- List<NameValuePair> commands = new ArrayList<NameValuePair>(1);
- commands.add(new BasicNameValuePair("command", command));
+ List<NameValuePair> commands = new ArrayList<>(1);
+ String encoded = command.replace(" ", "+").replace("#", "%23")
+ .replace("|", "%7C").replace(";", "%3B");
+ commands.add(new BasicNameValuePair("command", encoded));
- List<String> reply = new ArrayList<String>();
+ List<String> reply = new ArrayList<>();
BufferedReader response = null;
try
{
- response = HttpClientUtils.doHttpUrlPost(restUrl, commands, CONNECTION_TIMEOUT_MS,
- REST_REPLY_TIMEOUT_MS);
+ if (isChimeraX())
+ {
+ response = HttpClientUtils.doHttpGet(restUrl, commands,
+ CONNECTION_TIMEOUT_MS, REST_REPLY_TIMEOUT_MS);
+ }
+ else
+ {
+ response = HttpClientUtils.doHttpUrlPost(restUrl, commands,
+ CONNECTION_TIMEOUT_MS, REST_REPLY_TIMEOUT_MS);
+ }
String line = "";
while ((line = response.readLine()) != null)
{
{
return busy;
}
+
+ public Process getChimeraProcess()
+ {
+ return chimera;
+ }
+
+ public boolean isChimeraX()
+ {
+ return isChimeraX;
+ }
}