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