1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23  """The Molmol and Pymol base macro methods of the specific API for model-free analysis.""" 
 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, 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 or not hasattr(spin, 'model'): 
 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 or not hasattr(spin, 'model'): 
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 or not hasattr(spin, 'model'): 
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 or not hasattr(spin, 'model'): 
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           
179           
180   
181          elif data_type == 'amp_slow': 
182               
183              for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 
184                   
185                  if not spin.select or not hasattr(spin, 'model'): 
186                      continue 
187   
188                   
189                  if search('tm[0-9]', spin.model): 
190                      model = spin.model[1:] 
191                  else: 
192                      model = spin.model 
193   
194                   
195                  if spin.name == 'N': 
196                       
197                      if hasattr(spin, 'ts') and spin.ts != None: 
198                          self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 
199   
200                       
201                      elif (model == 'm2' or model == 'm4') and spin.te > 200 * 1e-12: 
202                          self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 
203   
204                       
205                      else: 
206                          self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 
207   
208           
209           
210   
211          elif data_type == 'te': 
212               
213              for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 
214                   
215                  if not spin.select or not hasattr(spin, 'model'): 
216                      continue 
217   
218                   
219                  if not hasattr(spin, 'te') or spin.te == None: 
220                      continue 
221   
222                   
223                  if spin.name == 'N': 
224                      self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list) 
225   
226   
227           
228           
229   
230          elif data_type == 'tf': 
231               
232              for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 
233                   
234                  if not spin.select or not hasattr(spin, 'model'): 
235                      continue 
236   
237                   
238                  if not hasattr(spin, 'tf') or spin.tf == None: 
239                      continue 
240   
241                   
242                  if spin.name == 'N': 
243                      self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list) 
244   
245   
246           
247           
248   
249          elif data_type == 'ts': 
250               
251              for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 
252                   
253                  if not spin.select or not hasattr(spin, 'model'): 
254                      continue 
255   
256                   
257                  if not hasattr(spin, 'ts') or spin.ts == None: 
258                      continue 
259   
260                   
261                  if colour_start == None: 
262                      colour_start = 'blue' 
263                  if colour_end == None: 
264                      colour_end = 'black' 
265   
266                   
267                  if spin.name == 'N': 
268                      self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list) 
269   
270   
271           
272           
273   
274          elif data_type == 'time_fast': 
275               
276              for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 
277                   
278                  if not spin.select or not hasattr(spin, 'model'): 
279                      continue 
280   
281                   
282                  if search('tm[0-9]', spin.model): 
283                      model = spin.model[1:] 
284                  else: 
285                      model = spin.model 
286   
287                   
288                  if spin.name == 'N': 
289                       
290                      if hasattr(spin, 'tf') and spin.tf != None: 
291                          self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list) 
292   
293                       
294                      elif (model == 'm2' or model == 'm4') and spin.te <= 200e-12: 
295                          self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list) 
296   
297                       
298                       
299                      else: 
300                          self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 
301   
302   
303           
304           
305   
306          elif data_type == 'time_slow': 
307               
308              for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 
309                   
310                  if not spin.select or not hasattr(spin, 'model'): 
311                      continue 
312   
313                   
314                  if search('tm[0-9]', spin.model): 
315                      model = spin.model[1:] 
316                  else: 
317                      model = spin.model 
318   
319                   
320                  if colour_start == None: 
321                      colour_start = 'blue' 
322                  if colour_end == None: 
323                      colour_end = 'black' 
324   
325                   
326                  if spin.name == 'N': 
327                       
328                      if hasattr(spin, 'ts') and spin.ts != None: 
329                          self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list) 
330   
331                       
332                      elif (model == 'm2' or model == 'm4') and spin.te > 200e-12: 
333                          self.classic_correlation_time(res_num, spin.te / 10.0, colour_start, colour_end, colour_list) 
334   
335                       
336                      else: 
337                          self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 
338   
339   
340           
341           
342   
343          elif data_type == 'rex': 
344               
345              for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 
346                   
347                  if not spin.select or not hasattr(spin, 'model'): 
348                      continue 
349   
350                   
351                  if spin.name == 'N': 
352                       
353                      if hasattr(spin, 'rex') and spin.rex != None: 
354                          self.classic_rex(res_num, spin.rex, colour_start, colour_end, colour_list) 
355   
356                       
357                      else: 
358                          self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 
359   
360   
361           
362           
363   
364          else: 
365              raise RelaxUnknownDataTypeError(data_type) 
 366   
367   
369          """Function for generating the bond width and colours for correlation times.""" 
370   
371           
372          te = te * 1e12 
373   
374           
375          width = 2.0 - 200.0 / (te + 100.0) 
376   
377           
378          if width <= 0.0: 
379              width = 0.001 
380   
381           
382          colour_value = 1.0 / (te / 100.0 + 1.0) 
383   
384           
385          if colour_value < 0.0: 
386              colour_value = 0.0 
387          elif colour_value > 1.0: 
388              colour_value = 1.0 
389   
390           
391          if colour_start == None: 
392              colour_start = 'turquoise' 
393          if colour_end == None: 
394              colour_end = 'blue' 
395   
396           
397          rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list) 
398   
399           
400          self.classic_colour(res_num, width, rgb_array) 
 401   
402   
404          """Function for generating the bond width and colours for order parameters.""" 
405   
406           
407          if s2 <= 0.0: 
408              width = 2.0 
409          else: 
410              width = 2.0 * (1.0 - s2**2) 
411   
412           
413          if width <= 0.0: 
414              width = 0.001 
415   
416           
417          colour_value = s2 ** 4 
418   
419           
420          if colour_value < 0.0: 
421              colour_value = 0.0 
422          elif colour_value > 1.0: 
423              colour_value = 1.0 
424   
425           
426          if colour_start == None: 
427              colour_start = 'red' 
428          if colour_end == None: 
429              colour_end = 'yellow' 
430   
431           
432          rgb_array = linear_gradient(colour_value, colour_start, colour_end, colour_list) 
433   
434           
435          self.classic_colour(res_num, width, rgb_array) 
 436   
437   
438 -    def classic_rex(self, res_num, rex, colour_start, colour_end, colour_list): 
 439          """Function for generating the bond width and colours for correlation times.""" 
440   
441           
442          if not hasattr(cdp, 'frq'): 
443              raise RelaxError("No spectrometer frequency information is present in the current data pipe.") 
444          if hasattr(cdp, 'ri_ids'): 
445              frq = cdp.frq[cdp.ri_ids[0]] 
446          else:        
447              frqs = sorted(cdp.frq.values()) 
448              frq = frqs[-1] 
449   
450           
451          rex = rex * (2.0 * pi * frq)**2 
452   
453           
454          width = 2.0 - 2.0 / (rex/5.0 + 1.0) 
455   
456           
457          if width <= 0.0: 
458              width = 0.001 
459   
460           
461          colour_value = 1.0 / (rex + 1.0) 
462   
463           
464          if colour_value < 0.0: 
465              colour_value = 0.0 
466          elif colour_value > 1.0: 
467              colour_value = 1.0 
468   
469           
470          if colour_start == None: 
471              colour_start = 'yellow' 
472          if colour_end == None: 
473              colour_end = 'red' 
474   
475           
476          rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list) 
477   
478           
479          self.classic_colour(res_num, width, rgb_array) 
 480   
481   
482 -    def create_macro(self, data_type, style=None, colour_start=None, colour_end=None, colour_list=None, spin_id=None): 
 483          """Create and return an array of macros of the model-free parameters. 
484   
485          @param data_type:       The parameter name or data type. 
486          @type data_type:        str 
487          @keyword style:         The Molmol style. 
488          @type style:            None or str 
489          @keyword colour_start:  The starting colour (must be a MOLMOL or X11 name). 
490          @type colour_start:     str 
491          @keyword colour_end:    The ending colour (must be a MOLMOL or X11 name). 
492          @type colour_end:       str 
493          @keyword colour_list:   The colour list used, either 'molmol' or 'x11'. 
494          @type colour_list:      str 
495          @keyword spin_id:       The spin identification string. 
496          @type spin_id:          str 
497          """ 
498   
499           
500          self.commands = [] 
501   
502           
503          if style == 'classic': 
504              self.classic_style(data_type, colour_start, colour_end, colour_list, spin_id) 
505   
506           
507          else: 
508              raise RelaxStyleError(style) 
509   
510           
511          return self.commands 
  512