Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
PymolBindingModel | 42 | 54 | 24 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
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. | |
11 | * | |
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. | |
16 | * | |
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. | |
20 | */ | |
21 | package jalview.gui; | |
22 | ||
23 | import java.util.ArrayList; | |
24 | import java.util.HashMap; | |
25 | import java.util.List; | |
26 | import java.util.Map; | |
27 | ||
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; | |
41 | ||
42 | public class PymolBindingModel extends AAStructureBindingModel | |
43 | { | |
44 | /* | |
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 | |
48 | */ | |
49 | private static String LABEL_FORMAT = "\"%s %s\" % (resn,resi)"; | |
50 | ||
51 | private PymolManager pymolManager; | |
52 | ||
53 | /* | |
54 | * full paths to structure files opened in PyMOL | |
55 | */ | |
56 | List<String> structureFiles = new ArrayList<>(); | |
57 | ||
58 | /* | |
59 | * lookup from file path to PyMOL object name | |
60 | */ | |
61 | Map<String, String> pymolObjects = new HashMap<>(); | |
62 | ||
63 | private String lastLabelSpec; | |
64 | ||
65 | /** | |
66 | * Constructor | |
67 | * | |
68 | * @param viewer | |
69 | * @param ssm | |
70 | * @param pdbentry | |
71 | * @param sequenceIs | |
72 | */ | |
73 | 0 | public PymolBindingModel(StructureViewerBase viewer, |
74 | StructureSelectionManager ssm, PDBEntry[] pdbentry, | |
75 | SequenceI[][] sequenceIs) | |
76 | { | |
77 | 0 | super(ssm, pdbentry, sequenceIs, null); |
78 | 0 | pymolManager = new PymolManager(); |
79 | 0 | setStructureCommands(new PymolCommands()); |
80 | 0 | setViewer(viewer); |
81 | } | |
82 | ||
83 | 0 | @Override |
84 | public String[] getStructureFiles() | |
85 | { | |
86 | 0 | return structureFiles.toArray(new String[structureFiles.size()]); |
87 | } | |
88 | ||
89 | 0 | @Override |
90 | public void highlightAtoms(List<AtomSpec> atoms) | |
91 | { | |
92 | /* | |
93 | * https://pymolwiki.org/index.php/indicate#examples | |
94 | */ | |
95 | 0 | StringBuilder sb = new StringBuilder(); |
96 | 0 | for (AtomSpec atom : atoms) |
97 | { | |
98 | // todo promote to StructureCommandsI.showLabel() | |
99 | 0 | String modelId = getModelIdForFile(atom.getPdbFile()); |
100 | 0 | sb.append(String.format(" %s//%s/%d/*", modelId, atom.getChain(), |
101 | atom.getPdbResNum())); | |
102 | } | |
103 | 0 | String labelSpec = sb.toString(); |
104 | 0 | if (labelSpec.equals(lastLabelSpec)) |
105 | { | |
106 | 0 | return; |
107 | } | |
108 | 0 | StructureCommandI command = new StructureCommand("indicate", labelSpec); |
109 | 0 | executeCommand(command, false); |
110 | ||
111 | 0 | lastLabelSpec = labelSpec; |
112 | } | |
113 | ||
114 | 0 | @Override |
115 | public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp) | |
116 | { | |
117 | 0 | return new SequenceRenderer(avp.getAlignViewport()); |
118 | } | |
119 | ||
120 | 0 | @Override |
121 | protected List<String> executeCommand(StructureCommandI command, | |
122 | boolean getReply) | |
123 | { | |
124 | // jalview.bin.Console.outPrintln(command.toString()); // debug | |
125 | 0 | return pymolManager.sendCommand(command, getReply); |
126 | } | |
127 | ||
128 | 0 | @Override |
129 | protected String getModelIdForFile(String file) | |
130 | { | |
131 | 0 | return pymolObjects.containsKey(file) ? pymolObjects.get(file) : ""; |
132 | } | |
133 | ||
134 | 0 | @Override |
135 | protected ViewerType getViewerType() | |
136 | { | |
137 | 0 | return ViewerType.PYMOL; |
138 | } | |
139 | ||
140 | 0 | @Override |
141 | public boolean isViewerRunning() | |
142 | { | |
143 | 0 | return pymolManager != null && pymolManager.isPymolLaunched(); |
144 | } | |
145 | ||
146 | 0 | @Override |
147 | public void closeViewer(boolean closePymol) | |
148 | { | |
149 | 0 | super.closeViewer(closePymol); |
150 | 0 | pymolManager = null; |
151 | } | |
152 | ||
153 | 0 | public boolean launchPymol() |
154 | { | |
155 | 0 | if (pymolManager.isPymolLaunched()) |
156 | { | |
157 | 0 | return true; |
158 | } | |
159 | ||
160 | 0 | Process pymol = pymolManager.launchPymol(); |
161 | 0 | if (pymol != null) |
162 | { | |
163 | // start listening for PyMOL selections - how?? | |
164 | 0 | startExternalViewerMonitor(pymol); |
165 | } | |
166 | else | |
167 | { | |
168 | 0 | Console.error("Failed to launch PyMOL!"); |
169 | } | |
170 | 0 | return pymol != null; |
171 | } | |
172 | ||
173 | 0 | public void openFile(PDBEntry pe) |
174 | { | |
175 | // todo : check not already open, remap / rename, etc | |
176 | 0 | String file = pe.getFile(); |
177 | 0 | StructureCommandI cmd = getCommandGenerator().loadFile(file); |
178 | ||
179 | /* | |
180 | * a second parameter sets the pdbid as the loaded PyMOL object name | |
181 | */ | |
182 | 0 | String pdbId = pe.getId(); |
183 | 0 | try |
184 | { | |
185 | 0 | String safePDBId = java.net.URLEncoder.encode(pdbId, "UTF-8"); |
186 | 0 | pdbId = safePDBId.replace('%', '_'); |
187 | 0 | pdbId = pdbId.replace("-", "__"); |
188 | 0 | char fc = pdbId.charAt(0); |
189 | // put an 's' before any numerics | |
190 | 0 | if (fc >= '0' && fc <= '9') |
191 | { | |
192 | 0 | pdbId = 's' + pdbId; |
193 | } | |
194 | // pdbId.replace('-', 0) | |
195 | } catch (Exception x) | |
196 | { | |
197 | 0 | Console.error("Unxpected encoding exception for '" + pdbId + "'", x); |
198 | } | |
199 | 0 | cmd.addParameter(pdbId); |
200 | ||
201 | 0 | executeCommand(cmd, false); |
202 | ||
203 | 0 | pymolObjects.put(file, pdbId); |
204 | 0 | if (!structureFiles.contains(file)) |
205 | { | |
206 | 0 | structureFiles.add(file); |
207 | } | |
208 | 0 | if (getSsm() != null) |
209 | { | |
210 | 0 | getSsm().addStructureViewerListener(this); |
211 | } | |
212 | ||
213 | } | |
214 | ||
215 | 0 | @Override |
216 | protected String getModelId(int pdbfnum, String file) | |
217 | { | |
218 | 0 | return file; |
219 | } | |
220 | ||
221 | /** | |
222 | * Returns the file extension to use for a saved viewer session file (.pse) | |
223 | * | |
224 | * @return | |
225 | * @see https://pymolwiki.org/index.php/Save | |
226 | */ | |
227 | 0 | @Override |
228 | public String getSessionFileExtension() | |
229 | { | |
230 | 0 | return ".pse"; |
231 | } | |
232 | ||
233 | 0 | @Override |
234 | public String getHelpURL() | |
235 | { | |
236 | 0 | return "https://pymolwiki.org/"; |
237 | } | |
238 | ||
239 | /** | |
240 | * Constructs and sends commands to set atom properties for visible Jalview | |
241 | * features on residues mapped to structure | |
242 | * | |
243 | * @param avp | |
244 | * @return | |
245 | */ | |
246 | 0 | public int sendFeaturesToViewer(AlignmentViewPanel avp) |
247 | { | |
248 | // todo pull up this and JalviewChimeraBinding variant | |
249 | 0 | Map<String, Map<Object, AtomSpecModel>> featureValues = buildFeaturesMap( |
250 | avp); | |
251 | 0 | List<StructureCommandI> commands = getCommandGenerator() |
252 | .setAttributes(featureValues); | |
253 | 0 | executeCommands(commands, false, null); |
254 | 0 | return commands.size(); |
255 | } | |
256 | ||
257 | } |