From 4194c2c98f734d6d43f64a66e506995b5a0f64da Mon Sep 17 00:00:00 2001 From: gmungoc Date: Fri, 13 Dec 2019 14:57:36 +0000 Subject: [PATCH] JAL-2422 basic proof of concept of ChimeraX opened/coloured by Jalview --- .../edu/ucsf/rbvi/strucviz2/ChimeraManager.java | 80 +++++++++++----- src/jalview/ext/rbvi/chimera/AtomSpecModel.java | 98 ++++++++++++++++++-- src/jalview/ext/rbvi/chimera/ChimeraCommands.java | 57 ++++++++---- .../ext/rbvi/chimera/JalviewChimeraBinding.java | 71 ++++++++------ src/jalview/ws/HttpClientUtils.java | 62 +++++++++++++ .../ext/rbvi/chimera/ChimeraCommandsTest.java | 27 +++--- 6 files changed, 311 insertions(+), 84 deletions(-) diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java index a910a5a..a322f0b 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java @@ -254,7 +254,7 @@ public class ChimeraManager for (ChimeraModel chimeraModel : modelList) { // get model color - Color modelColor = getModelColor(chimeraModel); + Color modelColor = isChimeraX() ? null : getModelColor(chimeraModel); if (modelColor != null) { chimeraModel.setModelColor(modelColor); @@ -265,7 +265,7 @@ public class ChimeraManager // chimeraSend("repr stick "+newModel.toSpec()); // Create the information we need for the navigator - if (type != ModelType.SMILES) + if (type != ModelType.SMILES && !isChimeraX()) { addResidues(chimeraModel); } @@ -473,17 +473,19 @@ public class ChimeraManager public List getModelList() { List modelList = new ArrayList<>(); - List list = sendChimeraCommand("list models type molecule", - true); - if (list != null) - { - for (String modelLine : list) - { - ChimeraModel chimeraModel = new ChimeraModel(modelLine); - modelList.add(chimeraModel); - } - } - return modelList; + modelList.add(new ChimeraModel("4zhp", ModelType.PDB_MODEL, 1, 0)); + return modelList; // ChimeraX doesn't have 'list models' command + // List list = sendChimeraCommand("list models type molecule", + // true); + // if (list != null) + // { + // for (String modelLine : list) + // { + // ChimeraModel chimeraModel = new ChimeraModel(modelLine); + // modelList.add(chimeraModel); + // } + // } + // return modelList; } /** @@ -555,6 +557,7 @@ public class ChimeraManager { // 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"); @@ -567,8 +570,16 @@ public class ChimeraManager 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 = ""; @@ -616,15 +627,23 @@ public class ChimeraManager { 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) @@ -762,6 +781,8 @@ public class ChimeraManager private volatile boolean busy = false; + private boolean isChimeraX; + /** * Send a command to Chimera. * @@ -775,7 +796,7 @@ public class ChimeraManager */ public List sendChimeraCommand(String command, boolean reply) { - // System.out.println("chimeradebug>> " + command); + System.out.println("chimeradebug>> " + command); if (!isChimeraLaunched() || command == null || "".equals(command.trim())) { @@ -822,14 +843,24 @@ public class ChimeraManager { String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run"; List commands = new ArrayList<>(1); - commands.add(new BasicNameValuePair("command", command)); + String encoded = command.replace(" ", "+").replace("#", "%23") + .replace("|", "%7C").replace(";", "%3B"); + commands.add(new BasicNameValuePair("command", encoded)); List 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) { @@ -901,4 +932,9 @@ public class ChimeraManager { return chimera; } + + public boolean isChimeraX() + { + return isChimeraX; + } } diff --git a/src/jalview/ext/rbvi/chimera/AtomSpecModel.java b/src/jalview/ext/rbvi/chimera/AtomSpecModel.java index 39d6704..a72844e 100644 --- a/src/jalview/ext/rbvi/chimera/AtomSpecModel.java +++ b/src/jalview/ext/rbvi/chimera/AtomSpecModel.java @@ -58,7 +58,7 @@ public class AtomSpecModel */ public AtomSpecModel() { - atomSpec = new TreeMap>>(); + atomSpec = new TreeMap<>(); } /** @@ -77,7 +77,7 @@ public class AtomSpecModel Map> modelData = atomSpec.get(model); if (modelData == null) { - atomSpec.put(model, modelData = new TreeMap>()); + atomSpec.put(model, modelData = new TreeMap<>()); } /* @@ -86,7 +86,7 @@ public class AtomSpecModel List chainData = modelData.get(chain); if (chainData == null) { - chainData = new ArrayList(); + chainData = new ArrayList<>(); modelData.put(chain, chainData); } @@ -150,7 +150,8 @@ public class AtomSpecModel /* * we have a break so append the last range */ - appendRange(sb, start, end, chain, firstPositionForModel); + appendRange(sb, start, end, chain, firstPositionForModel, + false); firstPositionForModel = false; start = range[0]; end = range[1]; @@ -162,7 +163,7 @@ public class AtomSpecModel */ if (!rangeList.isEmpty()) { - appendRange(sb, start, end, chain, firstPositionForModel); + appendRange(sb, start, end, chain, firstPositionForModel, false); firstPositionForModel = false; } } @@ -178,7 +179,7 @@ public class AtomSpecModel * @param firstPositionForModel */ protected void appendRange(StringBuilder sb, int start, int end, - String chain, boolean firstPositionForModel) + String chain, boolean firstPositionForModel, boolean isChimeraX) { if (!firstPositionForModel) { @@ -193,9 +194,88 @@ public class AtomSpecModel sb.append(start).append("-").append(end); } - sb.append("."); - if (!" ".equals(chain)) { - sb.append(chain); + if (!isChimeraX) + { + sb.append("."); + if (!" ".equals(chain)) + { + sb.append(chain); + } } } + + /** + * Returns the range(s) formatted as a ChimeraX atomspec, for example + *

+ * #1/A:2-20,30-40/B:10-20|#2/A:12-30 + * + * @return + */ + public String getAtomSpecX() + { + StringBuilder sb = new StringBuilder(128); + boolean firstModel = true; + for (Integer model : atomSpec.keySet()) + { + if (!firstModel) + { + sb.append("|"); + } + firstModel = false; + sb.append("#").append(model); + + final Map> modelData = atomSpec.get(model); + + for (String chain : modelData.keySet()) + { + boolean firstPositionForChain = true; + chain = " ".equals(chain) ? chain : chain.trim(); + sb.append("/").append(chain).append(":"); + List rangeList = modelData.get(chain); + + /* + * sort ranges into ascending start position order + */ + Collections.sort(rangeList, IntRangeComparator.ASCENDING); + + int start = rangeList.isEmpty() ? 0 : rangeList.get(0)[0]; + int end = rangeList.isEmpty() ? 0 : rangeList.get(0)[1]; + + Iterator iterator = rangeList.iterator(); + while (iterator.hasNext()) + { + int[] range = iterator.next(); + if (range[0] <= end + 1) + { + /* + * range overlaps or is contiguous with the last one + * - so just extend the end position, and carry on + * (unless this is the last in the list) + */ + end = Math.max(end, range[1]); + } + else + { + /* + * we have a break so append the last range + */ + appendRange(sb, start, end, chain, firstPositionForChain, true); + start = range[0]; + end = range[1]; + firstPositionForChain = false; + } + } + + /* + * and append the last range + */ + if (!rangeList.isEmpty()) + { + appendRange(sb, start, end, chain, firstPositionForChain, true); + } + firstPositionForChain = false; + } + } + return sb.toString(); + } } diff --git a/src/jalview/ext/rbvi/chimera/ChimeraCommands.java b/src/jalview/ext/rbvi/chimera/ChimeraCommands.java index 3caaac3..01458a8 100644 --- a/src/jalview/ext/rbvi/chimera/ChimeraCommands.java +++ b/src/jalview/ext/rbvi/chimera/ChimeraCommands.java @@ -64,17 +64,19 @@ public class ChimeraCommands * @param sr * @param fr * @param viewPanel + * @param isChimeraX * @return */ public static StructureMappingcommandSet[] getColourBySequenceCommand( StructureSelectionManager ssm, String[] files, SequenceI[][] sequence, SequenceRenderer sr, - AlignmentViewPanel viewPanel) + AlignmentViewPanel viewPanel, boolean isChimeraX) { Map colourMap = buildColoursMap(ssm, files, - sequence, sr, viewPanel); + sequence, sr, viewPanel, isChimeraX); - List colourCommands = buildColourCommands(colourMap); + List colourCommands = buildColourCommands(colourMap, + isChimeraX); StructureMappingcommandSet cs = new StructureMappingcommandSet( ChimeraCommands.class, null, @@ -96,10 +98,11 @@ public class ChimeraCommands * * * @param colourMap + * @param isChimeraX * @return */ protected static List buildColourCommands( - Map colourMap) + Map colourMap, boolean isChimeraX) { /* * This version concatenates all commands into a single String (semi-colon @@ -117,10 +120,17 @@ public class ChimeraCommands { sb.append("; "); } - sb.append("color ").append(colourCode).append(" "); + sb.append("color "); firstColour = false; final AtomSpecModel colourData = colourMap.get(colour); - sb.append(colourData.getAtomSpec()); + if (isChimeraX) + { + sb.append(colourData.getAtomSpecX()).append(" ").append(colourCode); + } + else + { + sb.append(colourCode).append(" ").append(colourData.getAtomSpec()); + } } commands.add(sb.toString()); return commands; @@ -187,11 +197,19 @@ public class ChimeraCommands * list of start/end ranges * Ordering is by order of addition (for colours and positions), natural ordering (for models and chains) * + * + * @param ssm + * @param files + * @param sequence + * @param sr + * @param viewPanel + * @param isChimeraX + * @return */ protected static Map buildColoursMap( StructureSelectionManager ssm, String[] files, SequenceI[][] sequence, SequenceRenderer sr, - AlignmentViewPanel viewPanel) + AlignmentViewPanel viewPanel, boolean isChimeraX) { FeatureRenderer fr = viewPanel.getFeatureRenderer(); FeatureColourFinder finder = new FeatureColourFinder(fr); @@ -203,6 +221,7 @@ public class ChimeraCommands for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { + final int modelNumber = pdbfnum + (isChimeraX ? 1 : 0); StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); if (mapping == null || mapping.length < 1) @@ -259,8 +278,8 @@ public class ChimeraCommands { if (startPos != -1) { - addAtomSpecRange(colourMap, lastColour, pdbfnum, startPos, - lastPos, lastChain); + addAtomSpecRange(colourMap, lastColour, modelNumber, + startPos, lastPos, lastChain); } startPos = pos; } @@ -271,7 +290,7 @@ public class ChimeraCommands // final colour range if (lastColour != null) { - addAtomSpecRange(colourMap, lastColour, pdbfnum, startPos, + addAtomSpecRange(colourMap, lastColour, modelNumber, startPos, lastPos, lastChain); } // break; @@ -316,23 +335,25 @@ public class ChimeraCommands /** * Constructs and returns Chimera commands to set attributes on residues - * corresponding to features in Jalview. Attribute names are the Jalview - * feature type, with a "jv_" prefix. + * corresponding to features in Jalview. Attribute names are the Jalview feature + * type, with a "jv_" prefix. * * @param ssm * @param files * @param seqs * @param viewPanel + * @param isChimeraX * @return */ public static StructureMappingcommandSet getSetAttributeCommandsForFeatures( StructureSelectionManager ssm, String[] files, SequenceI[][] seqs, - AlignmentViewPanel viewPanel) + AlignmentViewPanel viewPanel, boolean isChimeraX) { Map> featureMap = buildFeaturesMap( ssm, files, seqs, viewPanel); - List commands = buildSetAttributeCommands(featureMap); + List commands = buildSetAttributeCommands(featureMap, + isChimeraX); StructureMappingcommandSet cs = new StructureMappingcommandSet( ChimeraCommands.class, null, @@ -579,10 +600,12 @@ public class ChimeraCommands * * * @param featureMap + * @param isChimeraX * @return */ protected static List buildSetAttributeCommands( - Map> featureMap) + Map> featureMap, + boolean isChimeraX) { List commands = new ArrayList<>(); for (String featureType : featureMap.keySet()) @@ -608,7 +631,9 @@ public class ChimeraCommands featureValue = featureValue.replaceAll("\\'", "'"); sb.append("setattr r ").append(attributeName).append(" '") .append(featureValue).append("' "); - sb.append(values.get(value).getAtomSpec()); + AtomSpecModel atomSpecModel = values.get(value); + sb.append(isChimeraX ? atomSpecModel.getAtomSpecX() + : atomSpecModel.getAtomSpec()); commands.add(sb.toString()); } } diff --git a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index 00446f2..47ada53 100644 --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@ -76,9 +76,9 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel private static final String ALPHACARBON = "CA"; - private List chainNames = new ArrayList(); + private List chainNames = new ArrayList<>(); - private Hashtable chainFile = new Hashtable(); + private Hashtable chainFile = new Hashtable<>(); /* * Object through which we talk to Chimera @@ -106,7 +106,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel /* * Map of ChimeraModel objects keyed by PDB full local file name */ - private Map> chimeraMaps = new LinkedHashMap>(); + private Map> chimeraMaps = new LinkedHashMap<>(); String lastHighlightCommand; @@ -122,8 +122,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel /** * Open a PDB structure file in Chimera and set up mappings from Jalview. * - * We check if the PDB model id is already loaded in Chimera, if so don't - * reopen it. This is the case if Chimera has opened a saved session file. + * We check if the PDB model id is already loaded in Chimera, if so don't reopen + * it. This is the case if Chimera has opened a saved session file. * * @param pe * @return @@ -133,8 +133,9 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel String file = pe.getFile(); try { - List modelsToMap = new ArrayList(); - List oldList = viewer.getModelList(); + List modelsToMap = new ArrayList<>(); + List oldList = viewer.isChimeraX() ? new ArrayList<>() + : viewer.getModelList(); boolean alreadyOpen = false; /* @@ -156,13 +157,32 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel if (!alreadyOpen) { viewer.openModel(file, pe.getId(), ModelType.PDB_MODEL); - List newList = viewer.getModelList(); - // JAL-1728 newList.removeAll(oldList) does not work - for (ChimeraModel cm : newList) + if (viewer.isChimeraX()) { - if (cm.getModelName().equals(pe.getId())) + /* + * ChimeraX hack: force chimera model name to pdbId + */ + int modelNumber = chimeraMaps.size() + 1; + String command = "setattr #" + modelNumber + " models name " + + pe.getId(); + sendChimeraCommand(command, false); + modelsToMap.add(new ChimeraModel(pe.getId(), ModelType.PDB_MODEL, + modelNumber, 0)); + } + else + { + /* + * Chimera: query for actual models and find the one with + * matching model name - set in viewer.openModel() + */ + List newList = viewer.getModelList(); + // JAL-1728 newList.removeAll(oldList) does not work + for (ChimeraModel cm : newList) { - modelsToMap.add(cm); + if (cm.getModelName().equals(pe.getId())) + { + modelsToMap.add(cm); + } } } } @@ -200,9 +220,9 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel } /** - * Starts a thread that waits for the Chimera process to finish, so that we - * can then close the associated resources. This avoids leaving orphaned - * Chimera viewer panels in Jalview if the user closes Chimera. + * Starts a thread that waits for the Chimera process to finish, so that we can + * then close the associated resources. This avoids leaving orphaned Chimera + * viewer panels in Jalview if the user closes Chimera. */ protected void startChimeraProcessMonitor() { @@ -231,8 +251,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel } /** - * Start a dedicated HttpServer to listen for Chimera notifications, and tell - * it to start listening + * Start a dedicated HttpServer to listen for Chimera notifications, and tell it + * to start listening */ public void startChimeraListener() { @@ -699,7 +719,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel) { return ChimeraCommands.getColourBySequenceCommand(getSsm(), files, - getSequence(), sr, viewPanel); + getSequence(), sr, viewPanel, viewer.isChimeraX()); } /** @@ -757,9 +777,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel } /** - * Construct and send a command to highlight zero, one or more atoms. We do - * this by sending an "rlabel" command to show the residue label at that - * position. + * Construct and send a command to highlight zero, one or more atoms. We do this + * by sending an "rlabel" command to show the residue label at that position. */ @Override public void highlightAtoms(List atoms) @@ -857,7 +876,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel protected List convertStructureResiduesToAlignment( List structureSelection) { - List atomSpecs = new ArrayList(); + List atomSpecs = new ArrayList<>(); for (String atomSpec : structureSelection) { try @@ -1110,7 +1129,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel StructureMappingcommandSet commandSet = ChimeraCommands .getSetAttributeCommandsForFeatures(getSsm(), files, - getSequence(), avp); + getSequence(), avp, viewer.isChimeraX()); String[] commands = commandSet.commands; if (commands.length > 10) { @@ -1127,9 +1146,9 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel } /** - * Write commands to a temporary file, and send a command to Chimera to open - * the file as a commands script. For use when sending a large number of - * separate commands would overload the REST interface mechanism. + * Write commands to a temporary file, and send a command to Chimera to open the + * file as a commands script. For use when sending a large number of separate + * commands would overload the REST interface mechanism. * * @param commands */ diff --git a/src/jalview/ws/HttpClientUtils.java b/src/jalview/ws/HttpClientUtils.java index b19d606..8f97226 100644 --- a/src/jalview/ws/HttpClientUtils.java +++ b/src/jalview/ws/HttpClientUtils.java @@ -34,6 +34,7 @@ import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; @@ -167,4 +168,65 @@ public class HttpClientUtils return null; } } + + /** + * do an HTTP GET with URL-Encoded parameters passed in the Query string + * + * @param url + * @param vals + * @return Reader containing content, if any, or null if no entity returned. + * @throws IOException + * @throws ClientProtocolException + * @throws Exception + */ + public static BufferedReader doHttpGet(String url, + List vals, int connectionTimeoutMs, + int readTimeoutMs) throws ClientProtocolException, IOException + { + // todo use HttpClient 4.3 or later and class RequestConfig + HttpParams params = new BasicHttpParams(); + params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, + HttpVersion.HTTP_1_1); + if (connectionTimeoutMs > 0) + { + HttpConnectionParams.setConnectionTimeout(params, + connectionTimeoutMs); + } + if (readTimeoutMs > 0) + { + HttpConnectionParams.setSoTimeout(params, readTimeoutMs); + } + boolean first = true; + for (NameValuePair param : vals) + { + if (first) + { + url += "?"; + } + else + { + url += "&"; + } + url += param.getName(); + url += "="; + url += param.getValue(); + } + HttpClient httpclient = new DefaultHttpClient(params); + HttpGet httpGet = new HttpGet(url); + // UrlEncodedFormEntity ue = new UrlEncodedFormEntity(vals, "UTF-8"); + // httpGet.setEntity(ue); + HttpResponse response = httpclient.execute(httpGet); + HttpEntity resEntity = response.getEntity(); + + if (resEntity != null) + { + BufferedReader r = new BufferedReader( + new InputStreamReader(resEntity.getContent())); + return r; + } + else + { + return null; + } + } } diff --git a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java index 06a09df..8e68d86 100644 --- a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java +++ b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java @@ -59,7 +59,7 @@ public class ChimeraCommandsTest public void testBuildColourCommands() { - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); ChimeraCommands.addAtomSpecRange(map, Color.blue, 0, 2, 5, "A"); ChimeraCommands.addAtomSpecRange(map, Color.blue, 0, 7, 7, "B"); ChimeraCommands.addAtomSpecRange(map, Color.blue, 0, 9, 23, "A"); @@ -72,7 +72,7 @@ public class ChimeraCommandsTest // Colours should appear in the Chimera command in the order in which // they were added; within colour, by model, by chain, ranges in start order - String command = ChimeraCommands.buildColourCommands(map).get(0); + String command = ChimeraCommands.buildColourCommands(map, false).get(0); assertEquals( command, "color #0000ff #0:2-5.A,9-23.A,7.B|#1:1.A,4-7.B; color #ffff00 #1:3-5.A,8.A; color #ff0000 #0:3-9.A"); @@ -84,8 +84,8 @@ public class ChimeraCommandsTest /* * make a map of { featureType, {featureValue, {residue range specification } } } */ - Map> featuresMap = new LinkedHashMap>(); - Map featureValues = new HashMap(); + Map> featuresMap = new LinkedHashMap<>(); + Map featureValues = new HashMap<>(); /* * start with just one feature/value... @@ -94,7 +94,7 @@ public class ChimeraCommandsTest ChimeraCommands.addAtomSpecRange(featureValues, "X", 0, 8, 20, "A"); List commands = ChimeraCommands - .buildSetAttributeCommands(featuresMap); + .buildSetAttributeCommands(featuresMap, false); assertEquals(1, commands.size()); /* @@ -107,7 +107,8 @@ public class ChimeraCommandsTest ChimeraCommands.addAtomSpecRange(featureValues, "X", 0, 3, 9, "A"); // same feature value, contiguous range ChimeraCommands.addAtomSpecRange(featureValues, "X", 0, 21, 25, "A"); - commands = ChimeraCommands.buildSetAttributeCommands(featuresMap); + commands = ChimeraCommands.buildSetAttributeCommands(featuresMap, + false); assertEquals(1, commands.size()); assertEquals(commands.get(0), "setattr r jv_chain 'X' #0:3-25.A"); @@ -115,14 +116,16 @@ public class ChimeraCommandsTest ChimeraCommands.addAtomSpecRange(featureValues, "X", 0, 21, 25, "B"); // same feature value and chain, different model ChimeraCommands.addAtomSpecRange(featureValues, "X", 1, 26, 30, "A"); - commands = ChimeraCommands.buildSetAttributeCommands(featuresMap); + commands = ChimeraCommands.buildSetAttributeCommands(featuresMap, + false); assertEquals(1, commands.size()); assertEquals(commands.get(0), "setattr r jv_chain 'X' #0:3-25.A,21-25.B|#1:26-30.A"); // same feature, different value ChimeraCommands.addAtomSpecRange(featureValues, "Y", 0, 40, 50, "A"); - commands = ChimeraCommands.buildSetAttributeCommands(featuresMap); + commands = ChimeraCommands.buildSetAttributeCommands(featuresMap, + false); assertEquals(2, commands.size()); // commands are ordered by feature type but not by value // so use contains to test for the expected command: @@ -138,7 +141,8 @@ public class ChimeraCommandsTest "A"); // feature names are sanitised to change non-alphanumeric to underscore // feature values are sanitised to encode single quote characters - commands = ChimeraCommands.buildSetAttributeCommands(featuresMap); + commands = ChimeraCommands.buildSetAttributeCommands(featuresMap, + false); assertTrue(commands .contains("setattr r jv_side_chain_binding_ 'metal 'ion!' #0:7-15.A")); } @@ -189,7 +193,7 @@ public class ChimeraCommandsTest /* * map residues 1-10 to residues 21-30 (atoms 105-150) in structures */ - HashMap map = new HashMap(); + HashMap map = new HashMap<>(); for (int pos = 1; pos <= seq1.getLength(); pos++) { map.put(pos, new int[] { 20 + pos, 5 * (20 + pos) }); @@ -202,7 +206,8 @@ public class ChimeraCommandsTest ssm.addStructureMapping(sm2); StructureMappingcommandSet[] commands = ChimeraCommands - .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel); + .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel, + false); assertEquals(1, commands.length); assertEquals(1, commands[0].commands.length); String theCommand = commands[0].commands[0]; -- 1.7.10.2