1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """The module containing the base class for the model-free macros."""
25
26
27 from math import pi
28 from re import search
29
30
31 from colour import linear_gradient
32 from generic_fns.mol_res_spin import spin_loop
33 from relax_errors import RelaxFault, RelaxStyleError, RelaxUnknownDataTypeError
34
35
36
38 """The base class for the model-free analysis Molmol and PyMOL macro creation."""
39
40 classic_style_doc = ["Model-free classic style", """
41 Creator: Edward d'Auvergne
42
43 Argument string: "classic"
44
45 Description: The classic style draws the backbone of a protein in a cylindrical bond style. Rather than colouring the amino acids to which the NH bond belongs, the three covalent bonds of the peptide bond from Ca to Ca in which the NH bond is located are coloured. Deselected residues are shown as black lines.
46
47 Supported data types:
48 ____________________________________________________________________________________________
49 | | | |
50 | Data type | String | Description |
51 |________________|_____________|___________________________________________________________|
52 | | | |
53 | S2. | 's2' | The standard model-free order parameter, equal to S2f.S2s |
54 | | | for the two timescale models. The default colour |
55 | | | gradient starts at 'yellow' and ends at 'red'. |
56 | | | |
57 | S2f. | 's2f' | The order parameter of the faster of two internal |
58 | | | motions. Residues which are described by model-free |
59 | | | models m1 to m4, the single timescale models, are |
60 | | | illustrated as white neon bonds. The default colour |
61 | | | gradient is the same as that for the S2 data type. |
62 | | | |
63 | S2s. | 's2s' | The order parameter of the slower of two internal |
64 | | | motions. This functions exactly as S2f except that S2s |
65 | | | is plotted instead. |
66 | | | |
67 | Amplitude of | 'amp_fast' | Model independent display of the amplite of fast motions. |
68 | fast motions. | | For residues described by model-free models m5 to m8, the |
69 | | | value plotted is that of S2f. However, for residues |
70 | | | described by models m1 to m4, what is shown is dependent |
71 | | | on the timescale of the motions. This is because these |
72 | | | single timescale models can, at times, be perfect |
73 | | | approximations to the more complex two timescale models. |
74 | | | Hence if te is less than 200 ps, S2 is plotted. Otherwise |
75 | | | the peptide bond is coloured white. The default colour |
76 | | | gradient is the same as that for S2. |
77 | | | |
78 | Amplitude of | 'amp_slow' | Model independent display of the amplite of slow motions, |
79 | slow motions. | | arbitrarily defined as motions slower than 200 ps. For |
80 | | | residues described by model-free models m5 to m8, the |
81 | | | order parameter S2 is plotted if ts > 200 ps. For models |
82 | | | m1 to m4, S2 is plotted if te > 200 ps. The default |
83 | | | colour gradient is the same as that for S2. |
84 | | | |
85 | te. | 'te' | The correlation time, te. The default colour gradient |
86 | | | starts at 'turquoise' and ends at 'blue'. |
87 | | | |
88 | tf. | 'tf' | The correlation time, tf. The default colour gradient is |
89 | | | the same as that of te. |
90 | | | |
91 | ts. | 'ts' | The correlation time, ts. The default colour gradient |
92 | | | starts at 'blue' and ends at 'black'. |
93 | | | |
94 | Timescale of | 'time_fast' | Model independent display of the timescale of fast |
95 | fast motions | | motions. For models m5 to m8, only the parameter tf is |
96 | | | plotted. For models m2 and m4, the parameter te is |
97 | | | plotted only if it is less than 200 ps. All other |
98 | | | residues are assumed to have a correlation time of zero. |
99 | | | The default colour gradient is the same as that of te. |
100 | | | |
101 | Timescale of | 'time_slow' | Model independent display of the timescale of slow |
102 | slow motions | | motions. For models m5 to m8, only the parameter ts is |
103 | | | plotted. For models m2 and m4, the parameter te is |
104 | | | plotted only if it is greater than 200 ps. All other |
105 | | | residues are coloured white. The default colour gradient |
106 | | | is the same as that of ts. |
107 | | | |
108 | Chemical | 'rex' | The chemical exchange, Rex. Residues which experience no |
109 | exchange | | chemical exchange are coloured white. The default colour |
110 | | | gradient starts at 'yellow' and finishes at 'red'. |
111 |________________|_____________|___________________________________________________________|
112 """]
113
114 - def classic_style(self, data_type=None, colour_start=None, colour_end=None, colour_list=None, spin_id=None):
115 """The classic macro style.
116
117 @keyword data_type: The parameter name or data type.
118 @type data_type: str
119 @keyword colour_start: The starting colour (must be a MOLMOL or X11 name).
120 @type colour_start: str
121 @keyword colour_end: The ending colour (must be a MOLMOL or X11 name).
122 @type colour_end: str
123 @keyword colour_list: The colour list used, either 'molmol' or 'x11'.
124 @type colour_list: str
125 @keyword spin_id: The spin identification string.
126 @type spin_id: str
127 """
128
129
130
131
132
133 prev_res_num = None
134 num = 0
135
136
137 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
138
139 if prev_res_num == res_num:
140 raise RelaxError("Only a single spin per residue is allowed for the classic macro style.")
141
142
143 prev_res_num = res_num
144
145
146
147
148
149 self.classic_header()
150
151
152
153
154
155 if data_type == 's2':
156
157 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
158
159 if not spin.select:
160 continue
161
162
163 if not hasattr(spin, 's2') or spin.s2 == None:
164 continue
165
166
167 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
168
169
170
171
172
173 elif data_type == 's2f':
174
175 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
176
177 if not spin.select:
178 continue
179
180
181 if not hasattr(spin, 's2f') or spin.s2f == None:
182 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
183
184
185 else:
186 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list)
187
188
189
190
191
192 elif data_type == 's2s':
193
194 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
195
196 if not spin.select:
197 continue
198
199
200 if not hasattr(spin, 's2s') or spin.s2s == None:
201 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
202
203
204 else:
205 self.classic_order_param(res_num, spin.s2s, colour_start, colour_end, colour_list)
206
207
208
209
210
211 elif data_type == 'amp_fast':
212
213 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
214
215 if not spin.select:
216 continue
217
218
219 if search('tm[0-9]', spin.model):
220 model = spin.model[1:]
221 else:
222 model = spin.model
223
224
225 if hasattr(spin, 's2f') and spin.s2f != None:
226 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list)
227
228
229 elif model == 'm1' or model == 'm3':
230 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
231
232
233 elif (model == 'm2' or model == 'm4') and spin.te <= 200e-12:
234 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
235
236
237 elif (model == 'm2' or model == 'm4') and spin.te > 200e-12:
238 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
239
240
241 else:
242 raise RelaxFault
243
244
245
246
247
248 elif data_type == 'amp_slow':
249
250 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
251
252 if not spin.select:
253 continue
254
255
256 if search('tm[0-9]', spin.model):
257 model = spin.model[1:]
258 else:
259 model = spin.model
260
261
262 if hasattr(spin, 'ts') and spin.ts != None:
263 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
264
265
266 elif (model == 'm2' or model == 'm4') and spin.te > 200 * 1e-12:
267 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
268
269
270 else:
271 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
272
273
274
275
276 elif data_type == 'te':
277
278 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
279
280 if not spin.select:
281 continue
282
283
284 if not hasattr(spin, 'te') or spin.te == None:
285 continue
286
287
288 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list)
289
290
291
292
293
294 elif data_type == 'tf':
295
296 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
297
298 if not spin.select:
299 continue
300
301
302 if not hasattr(spin, 'tf') or spin.tf == None:
303 continue
304
305
306 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list)
307
308
309
310
311
312 elif data_type == 'ts':
313
314 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
315
316 if not spin.select:
317 continue
318
319
320 if not hasattr(spin, 'ts') or spin.ts == None:
321 continue
322
323
324 if colour_start == None:
325 colour_start = 'blue'
326 if colour_end == None:
327 colour_end = 'black'
328
329
330 self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list)
331
332
333
334
335
336 elif data_type == 'time_fast':
337
338 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
339
340 if not spin.select:
341 continue
342
343
344 if search('tm[0-9]', spin.model):
345 model = spin.model[1:]
346 else:
347 model = spin.model
348
349
350 if hasattr(spin, 'tf') and spin.tf != None:
351 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list)
352
353
354 elif (model == 'm2' or model == 'm4') and spin.te <= 200e-12:
355 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list)
356
357
358
359 else:
360 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
361
362
363
364
365
366 elif data_type == 'time_slow':
367
368 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
369
370 if not spin.select:
371 continue
372
373
374 if search('tm[0-9]', spin.model):
375 model = spin.model[1:]
376 else:
377 model = spin.model
378
379
380 if colour_start == None:
381 colour_start = 'blue'
382 if colour_end == None:
383 colour_end = 'black'
384
385
386 if hasattr(spin, 'ts') and spin.ts != None:
387 self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list)
388
389
390 elif (model == 'm2' or model == 'm4') and spin.te > 200e-12:
391 self.classic_correlation_time(res_num, spin.te / 10.0, colour_start, colour_end, colour_list)
392
393
394 else:
395 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
396
397
398
399
400
401 elif data_type == 'rex':
402
403 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
404
405 if not spin.select:
406 continue
407
408
409 if hasattr(spin, 'rex') and spin.rex != None:
410 self.classic_rex(res_num, spin.rex, colour_start, colour_end, colour_list)
411
412
413 else:
414 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
415
416
417
418
419
420 else:
421 raise RelaxUnknownDataTypeError(data_type)
422
423
425 """Function for generating the bond width and colours for correlation times."""
426
427
428 te = te * 1e12
429
430
431 width = 2.0 - 200.0 / (te + 100.0)
432
433
434 if width <= 0.0:
435 width = 0.001
436
437
438 colour_value = 1.0 / (te / 100.0 + 1.0)
439
440
441 if colour_value < 0.0:
442 colour_value = 0.0
443 elif colour_value > 1.0:
444 colour_value = 1.0
445
446
447 if colour_start == None:
448 colour_start = 'turquoise'
449 if colour_end == None:
450 colour_end = 'blue'
451
452
453 rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list)
454
455
456 self.classic_colour(res_num, width, rgb_array)
457
458
460 """Function for generating the bond width and colours for order parameters."""
461
462
463 if s2 <= 0.0:
464 width = 2.0
465 else:
466 width = 2.0 * (1.0 - s2**2)
467
468
469 if width <= 0.0:
470 width = 0.001
471
472
473 colour_value = s2 ** 4
474
475
476 if colour_value < 0.0:
477 colour_value = 0.0
478 elif colour_value > 1.0:
479 colour_value = 1.0
480
481
482 if colour_start == None:
483 colour_start = 'red'
484 if colour_end == None:
485 colour_end = 'yellow'
486
487
488 rgb_array = linear_gradient(colour_value, colour_start, colour_end, colour_list)
489
490
491 self.classic_colour(res_num, width, rgb_array)
492
493
494 - def classic_rex(self, res_num, rex, colour_start, colour_end, colour_list):
495 """Function for generating the bond width and colours for correlation times."""
496
497
498 rex = rex * (2.0 * pi * cdp.frq[cdp.ri_ids[0]])**2
499
500
501 width = 2.0 - 2.0 / (rex/5.0 + 1.0)
502
503
504 if width <= 0.0:
505 width = 0.001
506
507
508 colour_value = 1.0 / (rex + 1.0)
509
510
511 if colour_value < 0.0:
512 colour_value = 0.0
513 elif colour_value > 1.0:
514 colour_value = 1.0
515
516
517 if colour_start == None:
518 colour_start = 'yellow'
519 if colour_end == None:
520 colour_end = 'red'
521
522
523 rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list)
524
525
526 self.classic_colour(res_num, width, rgb_array)
527
528
529 - def create_macro(self, data_type, style=None, colour_start=None, colour_end=None, colour_list=None, spin_id=None):
530 """Create and return an array of macros of the model-free parameters.
531
532 @param data_type: The parameter name or data type.
533 @type data_type: str
534 @keyword style: The Molmol style.
535 @type style: None or str
536 @keyword colour_start: The starting colour (must be a MOLMOL or X11 name).
537 @type colour_start: str
538 @keyword colour_end: The ending colour (must be a MOLMOL or X11 name).
539 @type colour_end: str
540 @keyword colour_list: The colour list used, either 'molmol' or 'x11'.
541 @type colour_list: str
542 @keyword spin_id: The spin identification string.
543 @type spin_id: str
544 """
545
546
547 self.commands = []
548
549
550 if style == 'classic':
551 self.classic_style(data_type, colour_start, colour_end, colour_list, spin_id)
552
553
554 else:
555 raise RelaxStyleError(style)
556
557
558 return self.commands
559