2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
28 import jalview.api.AlignmentViewPanel;
29 import jalview.bin.Console;
30 import jalview.datamodel.PDBEntry;
31 import jalview.datamodel.SequenceI;
32 import jalview.ext.pymol.PymolCommands;
33 import jalview.ext.pymol.PymolManager;
34 import jalview.gui.StructureViewer.ViewerType;
35 import jalview.structure.AtomSpec;
36 import jalview.structure.AtomSpecModel;
37 import jalview.structure.StructureCommand;
38 import jalview.structure.StructureCommandI;
39 import jalview.structure.StructureSelectionManager;
40 import jalview.structures.models.AAStructureBindingModel;
42 public class PymolBindingModel extends AAStructureBindingModel
45 * format for labels shown on structures when mousing over sequence;
46 * see https://pymolwiki.org/index.php/Label#examples
47 * left not final so customisable e.g. with a Groovy script
49 private static String LABEL_FORMAT = "\"%s %s\" % (resn,resi)";
51 private PymolManager pymolManager;
54 * full paths to structure files opened in PyMOL
56 List<String> structureFiles = new ArrayList<>();
59 * lookup from file path to PyMOL object name
61 Map<String, String> pymolObjects = new HashMap<>();
63 private String lastLabelSpec;
73 public PymolBindingModel(StructureViewerBase viewer,
74 StructureSelectionManager ssm, PDBEntry[] pdbentry,
75 SequenceI[][] sequenceIs)
77 super(ssm, pdbentry, sequenceIs, null);
78 pymolManager = new PymolManager();
79 setStructureCommands(new PymolCommands());
84 public String[] getStructureFiles()
86 return structureFiles.toArray(new String[structureFiles.size()]);
90 public void highlightAtoms(List<AtomSpec> atoms)
93 * https://pymolwiki.org/index.php/indicate#examples
95 StringBuilder sb = new StringBuilder();
96 for (AtomSpec atom : atoms)
98 // todo promote to StructureCommandsI.showLabel()
99 String modelId = getModelIdForFile(atom.getPdbFile());
100 sb.append(String.format(" %s//%s/%d/*", modelId, atom.getChain(),
101 atom.getPdbResNum()));
103 String labelSpec = sb.toString();
104 if (labelSpec.equals(lastLabelSpec))
108 StructureCommandI command = new StructureCommand("indicate", labelSpec);
109 executeCommand(command, false);
111 lastLabelSpec = labelSpec;
115 public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp)
117 return new SequenceRenderer(avp.getAlignViewport());
121 protected List<String> executeCommand(StructureCommandI command,
124 // jalview.bin.Console.outPrintln(command.toString()); // debug
125 return pymolManager.sendCommand(command, getReply);
129 protected String getModelIdForFile(String file)
131 return pymolObjects.containsKey(file) ? pymolObjects.get(file) : "";
135 protected ViewerType getViewerType()
137 return ViewerType.PYMOL;
141 public boolean isViewerRunning()
143 return pymolManager != null && pymolManager.isPymolLaunched();
147 public void closeViewer(boolean closePymol)
149 super.closeViewer(closePymol);
153 public boolean launchPymol()
155 if (pymolManager.isPymolLaunched())
160 Process pymol = pymolManager.launchPymol();
163 // start listening for PyMOL selections - how??
164 startExternalViewerMonitor(pymol);
168 Console.error("Failed to launch PyMOL!");
170 return pymol != null;
173 public void openFile(PDBEntry pe)
175 // todo : check not already open, remap / rename, etc
176 String file = pe.getFile();
177 StructureCommandI cmd = getCommandGenerator().loadFile(file);
180 * a second parameter sets the pdbid as the loaded PyMOL object name
182 String pdbId = pe.getId();
185 String safePDBId = java.net.URLEncoder.encode(pdbId, "UTF-8");
186 pdbId = safePDBId.replace('%', '_');
187 pdbId = pdbId.replace("-", "__");
188 char fc = pdbId.charAt(0);
189 // put an 's' before any numerics
190 if (fc >= '0' && fc <= '9')
194 // pdbId.replace('-', 0)
195 } catch (Exception x)
197 Console.error("Unxpected encoding exception for '" + pdbId + "'", x);
199 cmd.addParameter(pdbId);
201 executeCommand(cmd, false);
203 pymolObjects.put(file, pdbId);
204 if (!structureFiles.contains(file))
206 structureFiles.add(file);
208 if (getSsm() != null)
210 getSsm().addStructureViewerListener(this);
216 protected String getModelId(int pdbfnum, String file)
222 * Returns the file extension to use for a saved viewer session file (.pse)
225 * @see https://pymolwiki.org/index.php/Save
228 public String getSessionFileExtension()
234 public String getHelpURL()
236 return "https://pymolwiki.org/";
240 * Constructs and sends commands to set atom properties for visible Jalview
241 * features on residues mapped to structure
246 public int sendFeaturesToViewer(AlignmentViewPanel avp)
248 // todo pull up this and JalviewChimeraBinding variant
249 Map<String, Map<Object, AtomSpecModel>> featureValues = buildFeaturesMap(
251 List<StructureCommandI> commands = getCommandGenerator()
252 .setAttributes(featureValues);
253 executeCommands(commands, false, null);
254 return commands.size();