1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """The module containing the base class for the model-free macros."""
24
25
26 from math import pi
27 from re import search
28
29
30 from colour import linear_gradient
31 from generic_fns.mol_res_spin import spin_loop
32 from relax_errors import RelaxError, RelaxFault, RelaxStyleError, RelaxUnknownDataTypeError
33 from user_functions.data import Uf_tables; uf_tables = Uf_tables()
34 from user_functions.objects import Desc_container
35
36
37
39 """The base class for the model-free analysis Molmol and PyMOL macro creation."""
40
41 classic_style_doc = Desc_container("Model-free classic style")
42 classic_style_doc.add_paragraph("Creator: Edward d'Auvergne")
43 classic_style_doc.add_paragraph("Argument string: \"classic\"")
44 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.")
45 classic_style_doc.add_paragraph("Supported data types:")
46 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.")
47 table.add_headings(["Data type", "String", "Description"])
48 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'."])
49 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."])
50 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."])
51 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."])
52 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."])
53 table.add_row(["te.", "'te'", "The correlation time, te. The default colour gradient starts at 'turquoise' and ends at 'blue'."])
54 table.add_row(["tf.", "'tf'", "The correlation time, tf. The default colour gradient is the same as that of te."])
55 table.add_row(["ts.", "'ts'", "The correlation time, ts. The default colour gradient starts at 'blue' and ends at 'black'."])
56 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."])
57 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."])
58 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'."])
59 classic_style_doc.add_table(table.label)
60
61 - def classic_style(self, data_type=None, colour_start=None, colour_end=None, colour_list=None, spin_id=None):
62 """The classic macro style.
63
64 @keyword data_type: The parameter name or data type.
65 @type data_type: str
66 @keyword colour_start: The starting colour (must be a MOLMOL or X11 name).
67 @type colour_start: str
68 @keyword colour_end: The ending colour (must be a MOLMOL or X11 name).
69 @type colour_end: str
70 @keyword colour_list: The colour list used, either 'molmol' or 'x11'.
71 @type colour_list: str
72 @keyword spin_id: The spin identification string.
73 @type spin_id: str
74 """
75
76
77
78
79 self.classic_header()
80
81
82
83
84
85 if data_type == 's2':
86
87 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
88
89 if not spin.select:
90 continue
91
92
93 if not hasattr(spin, 's2') or spin.s2 == None:
94 continue
95
96
97 if spin.name == 'N':
98 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
99
100
101
102
103
104 elif data_type == 's2f':
105
106 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
107
108 if not spin.select:
109 continue
110
111
112 if spin.name == 'N':
113
114 if not hasattr(spin, 's2f') or spin.s2f == None:
115 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
116
117
118 else:
119 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list)
120
121
122
123
124
125 elif data_type == 's2s':
126
127 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
128
129 if not spin.select:
130 continue
131
132
133 if spin.name == 'N':
134
135 if not hasattr(spin, 's2s') or spin.s2s == None:
136 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
137
138
139 else:
140 self.classic_order_param(res_num, spin.s2s, colour_start, colour_end, colour_list)
141
142
143
144
145
146 elif data_type == 'amp_fast':
147
148 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
149
150 if not spin.select:
151 continue
152
153
154 if search('tm[0-9]', spin.model):
155 model = spin.model[1:]
156 else:
157 model = spin.model
158
159
160 if spin.name == 'N':
161
162 if hasattr(spin, 's2f') and spin.s2f != None:
163 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list)
164
165
166 elif model == 'm1' or model == 'm3':
167 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
168
169
170 elif (model == 'm2' or model == 'm4') and spin.te <= 200e-12:
171 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
172
173
174 elif (model == 'm2' or model == 'm4') and spin.te > 200e-12:
175 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
176
177
178 else:
179 raise RelaxFault
180
181
182
183
184
185 elif data_type == 'amp_slow':
186
187 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
188
189 if not spin.select:
190 continue
191
192
193 if search('tm[0-9]', spin.model):
194 model = spin.model[1:]
195 else:
196 model = spin.model
197
198
199 if spin.name == 'N':
200
201 if hasattr(spin, 'ts') and spin.ts != None:
202 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
203
204
205 elif (model == 'm2' or model == 'm4') and spin.te > 200 * 1e-12:
206 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list)
207
208
209 else:
210 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
211
212
213
214
215 elif data_type == 'te':
216
217 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
218
219 if not spin.select:
220 continue
221
222
223 if not hasattr(spin, 'te') or spin.te == None:
224 continue
225
226
227 if spin.name == 'N':
228 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list)
229
230
231
232
233
234 elif data_type == 'tf':
235
236 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
237
238 if not spin.select:
239 continue
240
241
242 if not hasattr(spin, 'tf') or spin.tf == None:
243 continue
244
245
246 if spin.name == 'N':
247 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list)
248
249
250
251
252
253 elif data_type == 'ts':
254
255 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
256
257 if not spin.select:
258 continue
259
260
261 if not hasattr(spin, 'ts') or spin.ts == None:
262 continue
263
264
265 if colour_start == None:
266 colour_start = 'blue'
267 if colour_end == None:
268 colour_end = 'black'
269
270
271 if spin.name == 'N':
272 self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list)
273
274
275
276
277
278 elif data_type == 'time_fast':
279
280 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
281
282 if not spin.select:
283 continue
284
285
286 if search('tm[0-9]', spin.model):
287 model = spin.model[1:]
288 else:
289 model = spin.model
290
291
292 if spin.name == 'N':
293
294 if hasattr(spin, 'tf') and spin.tf != None:
295 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list)
296
297
298 elif (model == 'm2' or model == 'm4') and spin.te <= 200e-12:
299 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list)
300
301
302
303 else:
304 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
305
306
307
308
309
310 elif data_type == 'time_slow':
311
312 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
313
314 if not spin.select:
315 continue
316
317
318 if search('tm[0-9]', spin.model):
319 model = spin.model[1:]
320 else:
321 model = spin.model
322
323
324 if colour_start == None:
325 colour_start = 'blue'
326 if colour_end == None:
327 colour_end = 'black'
328
329
330 if spin.name == 'N':
331
332 if hasattr(spin, 'ts') and spin.ts != None:
333 self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list)
334
335
336 elif (model == 'm2' or model == 'm4') and spin.te > 200e-12:
337 self.classic_correlation_time(res_num, spin.te / 10.0, colour_start, colour_end, colour_list)
338
339
340 else:
341 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1])
342
343
344
345
346
347 elif data_type == 'rex':
348
349 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
350
351 if not spin.select:
352 continue
353
354
355 if spin.name == 'N':
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