Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
PymolCommandsTest | 41 | 136 | 19 |
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.ext.pymol; | |
22 | ||
23 | import static org.testng.Assert.assertEquals; | |
24 | import static org.testng.Assert.assertTrue; | |
25 | ||
26 | import java.awt.Color; | |
27 | import java.util.HashMap; | |
28 | import java.util.LinkedHashMap; | |
29 | import java.util.List; | |
30 | import java.util.Map; | |
31 | ||
32 | import org.testng.annotations.BeforeClass; | |
33 | import org.testng.annotations.Test; | |
34 | ||
35 | import jalview.ext.rbvi.chimera.ChimeraCommands; | |
36 | import jalview.structure.AtomSpecModel; | |
37 | import jalview.structure.StructureCommand; | |
38 | import jalview.structure.StructureCommandI; | |
39 | import jalview.structure.StructureCommandsI.AtomSpecType; | |
40 | ||
41 | public class PymolCommandsTest | |
42 | { | |
43 | private PymolCommands testee; | |
44 | ||
45 | 1 | @BeforeClass(alwaysRun = true) |
46 | public void setUp() | |
47 | { | |
48 | 1 | testee = new PymolCommands(); |
49 | } | |
50 | ||
51 | 1 | @Test(groups = { "Functional" }) |
52 | public void testColourBySequence() | |
53 | { | |
54 | ||
55 | 1 | Map<Object, AtomSpecModel> map = new LinkedHashMap<>(); |
56 | 1 | PymolCommands.addAtomSpecRange(map, Color.blue, "0", 2, 5, "A"); |
57 | 1 | PymolCommands.addAtomSpecRange(map, Color.blue, "0", 7, 7, "B"); |
58 | 1 | PymolCommands.addAtomSpecRange(map, Color.blue, "0", 9, 23, "A"); |
59 | 1 | PymolCommands.addAtomSpecRange(map, Color.blue, "1", 1, 1, "A"); |
60 | 1 | PymolCommands.addAtomSpecRange(map, Color.blue, "1", 4, 7, "B"); |
61 | 1 | PymolCommands.addAtomSpecRange(map, Color.yellow, "1", 8, 8, "A"); |
62 | 1 | PymolCommands.addAtomSpecRange(map, Color.yellow, "1", 3, 5, "A"); |
63 | 1 | PymolCommands.addAtomSpecRange(map, Color.red, "0", 3, 5, "A"); |
64 | 1 | PymolCommands.addAtomSpecRange(map, Color.red, "0", 6, 9, "A"); |
65 | ||
66 | // Colours should appear in the Pymol command in the order in which | |
67 | // they were added; within colour, by model, by chain, ranges in start order | |
68 | 1 | List<StructureCommandI> commands = testee.colourBySequence(map); |
69 | 1 | assertEquals(commands.size(), 3); |
70 | 1 | assertEquals(commands.get(0), new StructureCommand("color", "0x0000ff", |
71 | "0//A/2-5+9-23/ 0//B/7/ 1//A/1/ 1//B/4-7/")); | |
72 | 1 | assertEquals(commands.get(1), |
73 | new StructureCommand("color", "0xffff00", "1//A/3-5+8/")); | |
74 | 1 | assertEquals(commands.get(2), |
75 | new StructureCommand("color", "0xff0000", "0//A/3-9/")); | |
76 | } | |
77 | ||
78 | 1 | @Test(groups = "Functional") |
79 | public void testGetAtomSpec() | |
80 | { | |
81 | 1 | AtomSpecModel model = new AtomSpecModel(); |
82 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), ""); |
83 | 1 | model.addRange("1", 2, 4, "A"); |
84 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
85 | "1//A/2-4/"); | |
86 | 1 | model.addRange("1", 8, 8, "A"); |
87 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
88 | "1//A/2-4+8/"); | |
89 | 1 | model.addRange("1", 5, 7, "B"); |
90 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
91 | "1//A/2-4+8/ 1//B/5-7/"); | |
92 | 1 | model.addRange("1", 3, 5, "A"); |
93 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
94 | "1//A/2-5+8/ 1//B/5-7/"); | |
95 | 1 | model.addRange("0", 1, 4, "B"); |
96 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
97 | "0//B/1-4/ 1//A/2-5+8/ 1//B/5-7/"); | |
98 | 1 | model.addRange("0", 5, 9, "C"); |
99 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
100 | "0//B/1-4/ 0//C/5-9/ 1//A/2-5+8/ 1//B/5-7/"); | |
101 | 1 | model.addRange("1", 8, 10, "B"); |
102 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
103 | "0//B/1-4/ 0//C/5-9/ 1//A/2-5+8/ 1//B/5-10/"); | |
104 | 1 | model.addRange("1", 8, 9, "B"); |
105 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
106 | "0//B/1-4/ 0//C/5-9/ 1//A/2-5+8/ 1//B/5-10/"); | |
107 | 1 | model.addRange("0", 3, 10, "C"); // subsumes 5-9 |
108 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
109 | "0//B/1-4/ 0//C/3-10/ 1//A/2-5+8/ 1//B/5-10/"); | |
110 | 1 | model.addRange("5", 25, 35, " "); |
111 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.RESIDUE_ONLY), |
112 | "0//B/1-4/ 0//C/3-10/ 1//A/2-5+8/ 1//B/5-10/ 5///25-35/"); | |
113 | ||
114 | } | |
115 | ||
116 | 1 | @Test(groups = { "Functional" }) |
117 | public void testSuperposeStructures() | |
118 | { | |
119 | 1 | AtomSpecModel ref = new AtomSpecModel(); |
120 | 1 | ref.addRange("1", 12, 14, "A"); |
121 | 1 | ref.addRange("1", 18, 18, "B"); |
122 | 1 | ref.addRange("1", 22, 23, "B"); |
123 | 1 | AtomSpecModel toAlign = new AtomSpecModel(); |
124 | 1 | toAlign.addRange("2", 15, 17, "B"); |
125 | 1 | toAlign.addRange("2", 20, 21, "B"); |
126 | 1 | toAlign.addRange("2", 22, 22, "C"); |
127 | 1 | List<StructureCommandI> commands = testee.superposeStructures(ref, |
128 | toAlign, AtomSpecType.ALPHA); | |
129 | 1 | assertEquals(commands.size(), 4); |
130 | 1 | String refSpecCA = "(1//A/12-14/CA 1//B/18+22-23/CA"; |
131 | 1 | String toAlignSpecCA = "(2//B/15-17+20-21/CA 2//C/22/CA"; |
132 | 1 | String refSpec = "1//A/12-14/ 1//B/18+22-23/"; |
133 | 1 | String toAlignSpec = "2//B/15-17+20-21/ 2//C/22/"; |
134 | 1 | String altLoc = " and (altloc '' or altloc 'a'))"; |
135 | // super command: separate arguments for regions to align | |
136 | 1 | assertEquals(commands.get(1), new StructureCommand("pair_fit", |
137 | toAlignSpecCA + altLoc, refSpecCA + altLoc)); | |
138 | // show aligned regions: one argument for combined atom specs | |
139 | 1 | assertEquals(commands.get(3), new StructureCommand("show", "cartoon", |
140 | refSpec + " " + toAlignSpec)); | |
141 | } | |
142 | ||
143 | 1 | @Test(groups = "Functional") |
144 | public void testGetAtomSpec_alphaOnly() | |
145 | { | |
146 | 1 | AtomSpecModel model = new AtomSpecModel(); |
147 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), ""); |
148 | 1 | model.addRange("1", 2, 4, "A"); |
149 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
150 | "1//A/2-4/CA"); | |
151 | 1 | model.addRange("1", 8, 8, "A"); |
152 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
153 | "1//A/2-4+8/CA"); | |
154 | 1 | model.addRange("1", 5, 7, "B"); |
155 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
156 | "1//A/2-4+8/CA 1//B/5-7/CA"); | |
157 | 1 | model.addRange("1", 3, 5, "A"); |
158 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
159 | "1//A/2-5+8/CA 1//B/5-7/CA"); | |
160 | 1 | model.addRange("0", 1, 4, "B"); |
161 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
162 | "0//B/1-4/CA 1//A/2-5+8/CA 1//B/5-7/CA"); | |
163 | 1 | model.addRange("0", 5, 9, "C"); |
164 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
165 | "0//B/1-4/CA 0//C/5-9/CA 1//A/2-5+8/CA 1//B/5-7/CA"); | |
166 | 1 | model.addRange("1", 8, 10, "B"); |
167 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
168 | "0//B/1-4/CA 0//C/5-9/CA 1//A/2-5+8/CA 1//B/5-10/CA"); | |
169 | 1 | model.addRange("1", 8, 9, "B"); |
170 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
171 | "0//B/1-4/CA 0//C/5-9/CA 1//A/2-5+8/CA 1//B/5-10/CA"); | |
172 | 1 | model.addRange("0", 3, 10, "C"); // subsumes 5-9 |
173 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
174 | "0//B/1-4/CA 0//C/3-10/CA 1//A/2-5+8/CA 1//B/5-10/CA"); | |
175 | 1 | model.addRange("5", 25, 35, " "); |
176 | 1 | assertEquals(testee.getAtomSpec(model, AtomSpecType.ALPHA), |
177 | "0//B/1-4/CA 0//C/3-10/CA 1//A/2-5+8/CA 1//B/5-10/CA 5///25-35/CA"); | |
178 | } | |
179 | ||
180 | 1 | @Test(groups = "Functional") |
181 | public void testGetModelStartNo() | |
182 | { | |
183 | 1 | assertEquals(testee.getModelStartNo(), 0); |
184 | } | |
185 | ||
186 | 1 | @Test(groups = "Functional") |
187 | public void testGetResidueSpec() | |
188 | { | |
189 | 1 | assertEquals(testee.getResidueSpec("ALA"), "resn ALA"); |
190 | } | |
191 | ||
192 | 1 | @Test(groups = "Functional") |
193 | public void testShowBackbone() | |
194 | { | |
195 | 1 | List<StructureCommandI> cmds = testee.showBackbone(); |
196 | 1 | assertEquals(cmds.size(), 2); |
197 | 1 | assertEquals(cmds.get(0), new StructureCommand("hide", "everything")); |
198 | 1 | assertEquals(cmds.get(1), new StructureCommand("show", "ribbon")); |
199 | } | |
200 | ||
201 | 1 | @Test(groups = "Functional") |
202 | public void testColourByCharge() | |
203 | { | |
204 | 1 | List<StructureCommandI> cmds = testee.colourByCharge(); |
205 | 1 | assertEquals(cmds.size(), 4); |
206 | 1 | assertEquals(cmds.get(0), new StructureCommand("color", "white", "*")); |
207 | 1 | assertEquals(cmds.get(1), |
208 | new StructureCommand("color", "red", "resn ASP resn GLU")); | |
209 | 1 | assertEquals(cmds.get(2), |
210 | new StructureCommand("color", "blue", "resn LYS resn ARG")); | |
211 | 1 | assertEquals(cmds.get(3), |
212 | new StructureCommand("color", "yellow", "resn CYS")); | |
213 | } | |
214 | ||
215 | 1 | @Test(groups = "Functional") |
216 | public void testOpenCommandFile() | |
217 | { | |
218 | 1 | assertEquals(testee.openCommandFile("commands.pml"), |
219 | new StructureCommand("run", "commands.pml")); | |
220 | } | |
221 | ||
222 | 1 | @Test(groups = "Functional") |
223 | public void testSaveSession() | |
224 | { | |
225 | 1 | assertEquals(testee.saveSession("somewhere.pse"), |
226 | new StructureCommand("save", "somewhere.pse")); | |
227 | } | |
228 | ||
229 | 1 | @Test(groups = "Functional") |
230 | public void testOpenSession() | |
231 | { | |
232 | 1 | assertEquals(testee.openSession("/some/path"), |
233 | new StructureCommand("load", "/some/path", "", "0", "pse")); | |
234 | } | |
235 | ||
236 | 1 | @Test(groups = "Functional") |
237 | public void testColourByChain() | |
238 | { | |
239 | 1 | assertEquals(testee.colourByChain(), |
240 | new StructureCommand("spectrum", "chain")); | |
241 | } | |
242 | ||
243 | 1 | @Test(groups = "Functional") |
244 | public void testColourResidues() | |
245 | { | |
246 | 1 | assertEquals(testee.colourResidues("something", Color.MAGENTA), |
247 | new StructureCommand("color", "0xff00ff", "something")); | |
248 | } | |
249 | ||
250 | 1 | @Test(groups = "Functional") |
251 | public void testLoadFile() | |
252 | { | |
253 | 1 | assertEquals(testee.loadFile("/some/path"), |
254 | new StructureCommand("load", "/some/path")); | |
255 | } | |
256 | ||
257 | 1 | @Test(groups = "Functional") |
258 | public void testSetBackgroundColour() | |
259 | { | |
260 | 1 | assertEquals(testee.setBackgroundColour(Color.PINK), |
261 | new StructureCommand("bg_color", "0xffafaf")); | |
262 | } | |
263 | ||
264 | 1 | @Test(groups = "Functional") |
265 | public void testSetAttribute() | |
266 | { | |
267 | 1 | AtomSpecModel model = new AtomSpecModel(); |
268 | 1 | model.addRange("1", 89, 92, "A"); |
269 | 1 | model.addRange("2", 12, 20, "B"); |
270 | 1 | model.addRange("2", 8, 9, "B"); |
271 | 1 | assertEquals(testee.setAttribute("jv_kd", "27.3", model), |
272 | new StructureCommand("iterate", "1//A/89-92/ 2//B/8-9+12-20/", | |
273 | "p.jv_kd='27.3'")); | |
274 | } | |
275 | ||
276 | 1 | @Test(groups = { "Functional" }) |
277 | public void testSetAttributes() | |
278 | { | |
279 | /* | |
280 | * make a map of { featureType, {featureValue, {residue range specification } } } | |
281 | */ | |
282 | 1 | Map<String, Map<Object, AtomSpecModel>> featuresMap = new LinkedHashMap<>(); |
283 | 1 | Map<Object, AtomSpecModel> featureValues = new HashMap<>(); |
284 | ||
285 | /* | |
286 | * start with just one feature/value... | |
287 | */ | |
288 | 1 | featuresMap.put("chain", featureValues); |
289 | 1 | ChimeraCommands.addAtomSpecRange(featureValues, "X", "0", 8, 20, "A"); |
290 | ||
291 | 1 | List<StructureCommandI> commands = testee.setAttributes(featuresMap); |
292 | 1 | assertEquals(commands.size(), 1); |
293 | ||
294 | /* | |
295 | * feature name gets a jv_ namespace prefix | |
296 | */ | |
297 | 1 | assertEquals(commands.get(0), new StructureCommand("iterate", |
298 | "0//A/8-20/", "p.jv_chain='X'")); | |
299 | ||
300 | // add same feature value, overlapping range | |
301 | 1 | ChimeraCommands.addAtomSpecRange(featureValues, "X", "0", 3, 9, "A"); |
302 | // same feature value, contiguous range | |
303 | 1 | ChimeraCommands.addAtomSpecRange(featureValues, "X", "0", 21, 25, "A"); |
304 | 1 | commands = testee.setAttributes(featuresMap); |
305 | 1 | assertEquals(commands.size(), 1); |
306 | 1 | assertEquals(commands.get(0), new StructureCommand("iterate", |
307 | "0//A/3-25/", "p.jv_chain='X'")); | |
308 | ||
309 | // same feature value and model, different chain | |
310 | 1 | ChimeraCommands.addAtomSpecRange(featureValues, "X", "0", 21, 25, "B"); |
311 | // same feature value and chain, different model | |
312 | 1 | ChimeraCommands.addAtomSpecRange(featureValues, "X", "1", 26, 30, "A"); |
313 | 1 | commands = testee.setAttributes(featuresMap); |
314 | 1 | assertEquals(commands.size(), 1); |
315 | 1 | StructureCommand expected1 = new StructureCommand("iterate", |
316 | "0//A/3-25/ 0//B/21-25/ 1//A/26-30/", "p.jv_chain='X'"); | |
317 | 1 | assertEquals(commands.get(0), expected1); |
318 | ||
319 | // same feature, different value | |
320 | 1 | ChimeraCommands.addAtomSpecRange(featureValues, "Y", "0", 40, 50, "A"); |
321 | 1 | commands = testee.setAttributes(featuresMap); |
322 | 1 | assertEquals(2, commands.size()); |
323 | // commands are ordered by feature type but not by value | |
324 | // so test for the expected command in either order | |
325 | 1 | StructureCommandI cmd1 = commands.get(0); |
326 | 1 | StructureCommandI cmd2 = commands.get(1); |
327 | 1 | StructureCommand expected2 = new StructureCommand("iterate", |
328 | "0//A/40-50/", "p.jv_chain='Y'"); | |
329 | 1 | assertTrue(cmd1.equals(expected1) || cmd2.equals(expected1)); |
330 | // String expected2 = "setattr #0/A:40-50 res jv_chain 'Y' create true"; | |
331 | 1 | assertTrue(cmd1.equals(expected2) || cmd2.equals(expected2)); |
332 | ||
333 | 1 | featuresMap.clear(); |
334 | 1 | featureValues.clear(); |
335 | 1 | featuresMap.put("side-chain binding!", featureValues); |
336 | 1 | ChimeraCommands.addAtomSpecRange(featureValues, |
337 | "<html>metal <a href=\"http:a.b.c/x\"> 'ion!", "0", 7, 15, "A"); | |
338 | // feature names are sanitised to change non-alphanumeric to underscore | |
339 | // feature values are sanitised to encode single quote characters | |
340 | 1 | commands = testee.setAttributes(featuresMap); |
341 | 1 | assertEquals(commands.size(), 1); |
342 | 1 | StructureCommandI expected3 = new StructureCommand("iterate", |
343 | "0//A/7-15/", | |
344 | "p.jv_side_chain_binding_='<html>metal <a href=\"http:a.b.c/x\"> 'ion!'"); | |
345 | 1 | assertEquals(commands.get(0), expected3); |
346 | } | |
347 | ||
348 | 1 | @Test(groups = "Functional") |
349 | public void testCloseViewer() | |
350 | { | |
351 | 1 | assertEquals(testee.closeViewer(), new StructureCommand("quit")); |
352 | } | |
353 | } |