1 package jalview.ext.pymol;
4 import java.util.ArrayList;
8 import jalview.structure.AtomSpecModel;
9 import jalview.structure.StructureCommand;
10 import jalview.structure.StructureCommandI;
11 import jalview.structure.StructureCommandsBase;
14 * A class that generates commands to send to PyMol over its XML-RPC interface.
16 * Note that because the xml-rpc interface can only accept one command at a
17 * time, we can't concatenate commands, and must instead form and send them
20 * @see https://pymolwiki.org/index.php/Category:Commands
21 * @see https://pymolwiki.org/index.php/RPC
23 public class PymolCommands extends StructureCommandsBase
25 private static final StructureCommand CLOSE_PYMOL = new StructureCommand("quit");
27 private static final StructureCommand COLOUR_BY_CHAIN = new StructureCommand("spectrum", "chain");
29 private static final List<StructureCommandI> COLOR_BY_CHARGE = new ArrayList<>();
31 private static final List<StructureCommandI> SHOW_BACKBONE = new ArrayList<>();
34 COLOR_BY_CHARGE.add(new StructureCommand("color", "white", "*"));
36 .add(new StructureCommand("color", "red", "resn ASP resn GLU"));
38 new StructureCommand("color", "blue", "resn LYS resn ARG"));
40 .add(new StructureCommand("color", "yellow", "resn CYS"));
41 SHOW_BACKBONE.add(new StructureCommand("hide", "everything"));
42 SHOW_BACKBONE.add(new StructureCommand("show", "ribbon"));
46 public StructureCommandI colourByChain()
48 return COLOUR_BY_CHAIN;
52 public List<StructureCommandI> colourByCharge()
54 return COLOR_BY_CHARGE;
58 public StructureCommandI setBackgroundColour(Color col)
60 // https://pymolwiki.org/index.php/Bg_Color
61 return new StructureCommand("bg_color", getColourString(col));
65 * Returns a colour formatted suitable for use in viewer command syntax. For
66 * example, red is {@code "0xff0000"}.
71 protected String getColourString(Color c)
73 return String.format("0x%02x%02x%02x", c.getRed(), c.getGreen(),
78 public StructureCommandI focusView()
80 // https://pymol.org/dokuwiki/doku.php?id=command:zoom
81 // not currently documented on https://pymolwiki.org/index.php/Category:Commands
82 return new StructureCommand("zoom");
86 public List<StructureCommandI> showChains(List<String> toShow)
88 // https://pymolwiki.org/index.php/Show
89 List<StructureCommandI> commands = new ArrayList<>();
90 commands.add(new StructureCommand("hide", "everything"));
91 commands.add(new StructureCommand("show", "lines"));
92 StringBuilder chains = new StringBuilder();
93 for (String chain : toShow)
95 chains.append(" chain ").append(chain);
97 commands.add(new StructureCommand("show", "cartoon", chains.toString()));
102 public List<StructureCommandI> superposeStructures(AtomSpecModel refAtoms,
103 AtomSpecModel atomSpec)
105 // https://pymolwiki.org/index.php/Super
106 List<StructureCommandI> commands = new ArrayList<>();
107 String refAtomsAlphaOnly = getAtomSpec(refAtoms, true);
108 String atomSpec2AlphaOnly = getAtomSpec(atomSpec, true);
109 commands.add(new StructureCommand("super", refAtomsAlphaOnly,
110 atomSpec2AlphaOnly));
113 * and show superposed residues as cartoon
115 String refAtomsAll = getAtomSpec(refAtoms, false);
116 String atomSpec2All = getAtomSpec(atomSpec, false);
117 commands.add(new StructureCommand("show", "cartoon",
118 refAtomsAll + " " + atomSpec2All));
124 public StructureCommandI openCommandFile(String path)
126 // https://pymolwiki.org/index.php/Run
127 return new StructureCommand("run", path); // should be .pml
131 public StructureCommandI saveSession(String filepath)
133 // https://pymolwiki.org/index.php/Save#EXAMPLES
134 return new StructureCommand("save", filepath); // should be .pse
138 * Returns a selection string in PyMOL 'selection macro' format:
141 * modelId// chain/residues/
144 * If more than one chain, makes a selection expression for each, and they are
145 * separated by spaces.
147 * @see https://pymolwiki.org/index.php/Selection_Macros
150 public String getAtomSpec(AtomSpecModel model, boolean alphaOnly)
152 StringBuilder sb = new StringBuilder(64);
153 boolean first = true;
154 for (String modelId : model.getModels())
156 for (String chain : model.getChains(modelId))
163 List<int[]> rangeList = model.getRanges(modelId, chain);
164 chain = chain.trim();
165 sb.append(modelId).append("//").append(chain).append("/");
166 boolean firstRange = true;
167 for (int[] range : rangeList)
174 sb.append(String.valueOf(range[0]));
175 if (range[0] != range[1])
177 sb.append("-").append(String.valueOf(range[1]));
187 return sb.toString();
191 public List<StructureCommandI> showBackbone()
193 return SHOW_BACKBONE;
197 protected StructureCommandI colourResidues(String atomSpec, Color colour)
199 // https://pymolwiki.org/index.php/Color
200 return new StructureCommand("color", getColourString(colour), atomSpec);
204 protected String getResidueSpec(String residue)
206 // https://pymolwiki.org/index.php/Selection_Algebra
207 return "resn " + residue;
211 public StructureCommandI loadFile(String file)
213 return new StructureCommand("load", file);
217 * Overrides the default implementation (which generates concatenated
218 * commands) to generate one per colour (because the XML-RPC interface to
219 * PyMOL only accepts one command at a time)
225 public List<StructureCommandI> colourBySequence(
226 Map<Object, AtomSpecModel> colourMap)
228 List<StructureCommandI> commands = new ArrayList<>();
229 for (Object key : colourMap.keySet())
231 Color colour = (Color) key;
232 final AtomSpecModel colourData = colourMap.get(colour);
233 commands.add(getColourCommand(colourData, colour));
240 * Returns a viewer command to set the given atom property value on atoms
241 * specified by the AtomSpecModel, for example
244 * iterate 4zho//B/12-34,48-55/CA,jv_chain='primary'
247 * @param attributeName
248 * @param attributeValue
249 * @param atomSpecModel
252 protected StructureCommandI setAttribute(String attributeName,
253 String attributeValue,
254 AtomSpecModel atomSpecModel)
256 StringBuilder sb = new StringBuilder(128);
257 sb.append("p.").append(attributeName).append("='")
258 .append(attributeValue).append("'");
259 String atomSpec = getAtomSpec(atomSpecModel, false);
260 return new StructureCommand("iterate", atomSpec, sb.toString());
264 * Traverse the map of features/values/models/chains/positions to construct a
265 * list of 'set property' commands (one per distinct feature type and value).
266 * The values are stored in the 'p' dictionary of user-defined properties of
269 * The format of each command is
272 * <blockquote> iterate atomspec, p.featureName='value'
273 * e.g. iterate 4zho//A/23,28-29/CA, p.jv_Metal='Fe'
281 public List<StructureCommandI> setAttributes(
282 Map<String, Map<Object, AtomSpecModel>> featureMap)
284 List<StructureCommandI> commands = new ArrayList<>();
285 for (String featureType : featureMap.keySet())
287 String attributeName = makeAttributeName(featureType);
290 * todo: clear down existing attributes for this feature?
292 // commands.add(new StructureCommand("iterate", "all",
293 // "p."+attributeName+"='None'"); //?
295 Map<Object, AtomSpecModel> values = featureMap.get(featureType);
296 for (Object value : values.keySet())
299 * for each distinct value recorded for this feature type,
300 * add a command to set the attribute on the mapped residues
301 * Put values in single quotes, encoding any embedded single quotes
303 AtomSpecModel atomSpecModel = values.get(value);
304 String featureValue = value.toString();
305 featureValue = featureValue.replaceAll("\\'", "'");
306 StructureCommandI cmd = setAttribute(attributeName, featureValue,
316 public StructureCommandI openSession(String filepath)
318 // https://pymolwiki.org/index.php/Load
319 // this version of the command has no dependency on file extension
320 return new StructureCommand("load", filepath, "", "0", "pse");
324 public StructureCommandI closeViewer()
326 // https://pymolwiki.org/index.php/Quit