Package specific_fns :: Package model_free :: Module macro_base
[hide private]
[frames] | no frames]

Source Code for Module specific_fns.model_free.macro_base

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax.                                     # 
  6  #                                                                             # 
  7  # relax is free software; you can redistribute it and/or modify               # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation; either version 2 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # relax is distributed in the hope that it will be useful,                    # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with relax; if not, write to the Free Software                        # 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """The module containing the base class for the model-free macros.""" 
 25   
 26  # Python module imports. 
 27  from math import pi 
 28  from re import search 
 29   
 30  # relax module imports. 
 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   
39 -class Macro:
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 # Test the validity of the data (only a single spin per residue). 78 ################################################################# 79 80 # Init some variables. 81 prev_res_num = None 82 num = 0 83 84 # Loop over the spins. 85 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 86 # More than one spin. 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 # Update the previous residue number. 91 prev_res_num = res_num 92 93 94 # Generate the macro header. 95 ############################ 96 97 self.classic_header() 98 99 100 # S2. 101 ##### 102 103 if data_type == 's2': 104 # Loop over the spins. 105 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 106 # Skip deselected spins. 107 if not spin.select: 108 continue 109 110 # Skip spins which don't have an S2 value. 111 if not hasattr(spin, 's2') or spin.s2 == None: 112 continue 113 114 # S2 width and colour. 115 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 116 117 118 # S2f. 119 ###### 120 121 elif data_type == 's2f': 122 # Loop over the spins. 123 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 124 # Skip deselected spins. 125 if not spin.select: 126 continue 127 128 # Colour residues which don't have an S2f value white. 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 # S2f width and colour. 133 else: 134 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list) 135 136 137 # S2s. 138 ###### 139 140 elif data_type == 's2s': 141 # Loop over the spins. 142 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 143 # Skip deselected spins. 144 if not spin.select: 145 continue 146 147 # Colour residues which don't have an S2s value white. 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 # S2s width and colour. 152 else: 153 self.classic_order_param(res_num, spin.s2s, colour_start, colour_end, colour_list) 154 155 156 # Amplitude of fast motions. 157 ############################ 158 159 elif data_type == 'amp_fast': 160 # Loop over the spins. 161 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 162 # Skip deselected spins. 163 if not spin.select: 164 continue 165 166 # The model. 167 if search('tm[0-9]', spin.model): 168 model = spin.model[1:] 169 else: 170 model = spin.model 171 172 # S2f width and colour (for models m5 to m8). 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 # S2 width and colour (for models m1 and m3). 177 elif model == 'm1' or model == 'm3': 178 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 179 180 # S2 width and colour (for models m2 and m4 when te <= 200 ps). 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 # White bonds (for models m2 and m4 when te > 200 ps). 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 # Catch errors. 189 else: 190 raise RelaxFault 191 192 193 # Amplitude of slow motions. 194 ############################ 195 196 elif data_type == 'amp_slow': 197 # Loop over the spins. 198 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 199 # Skip deselected spins. 200 if not spin.select: 201 continue 202 203 # The model. 204 if search('tm[0-9]', spin.model): 205 model = spin.model[1:] 206 else: 207 model = spin.model 208 209 # S2 width and colour (for models m5 to m8). 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 # S2 width and colour (for models m2 and m4 when te > 200 ps). 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 # White bonds for fast motions. 218 else: 219 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 220 221 # te. 222 ##### 223 224 elif data_type == 'te': 225 # Loop over the spins. 226 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 227 # Skip deselected spins. 228 if not spin.select: 229 continue 230 231 # Skip spins which don't have a te value. 232 if not hasattr(spin, 'te') or spin.te == None: 233 continue 234 235 # te width and colour. 236 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list) 237 238 239 # tf. 240 ##### 241 242 elif data_type == 'tf': 243 # Loop over the spins. 244 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 245 # Skip deselected spins. 246 if not spin.select: 247 continue 248 249 # Skip spins which don't have a tf value. 250 if not hasattr(spin, 'tf') or spin.tf == None: 251 continue 252 253 # tf width and colour. 254 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list) 255 256 257 # ts. 258 ##### 259 260 elif data_type == 'ts': 261 # Loop over the spins. 262 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 263 # Skip deselected spins. 264 if not spin.select: 265 continue 266 267 # Skip spins which don't have a ts value. 268 if not hasattr(spin, 'ts') or spin.ts == None: 269 continue 270 271 # The default start and end colours. 272 if colour_start == None: 273 colour_start = 'blue' 274 if colour_end == None: 275 colour_end = 'black' 276 277 # ts width and colour. 278 self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list) 279 280 281 # Timescale of fast motions. 282 ############################ 283 284 elif data_type == 'time_fast': 285 # Loop over the spins. 286 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 287 # Skip deselected spins. 288 if not spin.select: 289 continue 290 291 # The model. 292 if search('tm[0-9]', spin.model): 293 model = spin.model[1:] 294 else: 295 model = spin.model 296 297 # tf width and colour (for models m5 to m8). 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 # te width and colour (for models m2 and m4 when te <= 200 ps). 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 # All other residues are assumed to have a fast correlation time of zero (statistically zero, not real zero!). 306 # Colour these bonds white. 307 else: 308 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 309 310 311 # Timescale of slow motions. 312 ############################ 313 314 elif data_type == 'time_slow': 315 # Loop over the spins. 316 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 317 # Skip deselected spins. 318 if not spin.select: 319 continue 320 321 # The model. 322 if search('tm[0-9]', spin.model): 323 model = spin.model[1:] 324 else: 325 model = spin.model 326 327 # The default start and end colours. 328 if colour_start == None: 329 colour_start = 'blue' 330 if colour_end == None: 331 colour_end = 'black' 332 333 # ts width and colour (for models m5 to m8). 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 # te width and colour (for models m2 and m4 when te > 200 ps). 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 # White bonds for the rest. 342 else: 343 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 344 345 346 # Rex. 347 ###### 348 349 elif data_type == 'rex': 350 # Loop over the spins. 351 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 352 # Skip deselected spins. 353 if not spin.select: 354 continue 355 356 # Residues which chemical exchange. 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 # White bonds for the rest. 361 else: 362 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 363 364 365 # Unknown data type. 366 #################### 367 368 else: 369 raise RelaxUnknownDataTypeError(data_type)
370 371
372 - def classic_correlation_time(self, res_num, te, colour_start, colour_end, colour_list):
373 """Function for generating the bond width and colours for correlation times.""" 374 375 # The te value in picoseconds. 376 te = te * 1e12 377 378 # The bond width (aiming for a width range of 2 to 0 for te values of 0 to 10 ns). 379 width = 2.0 - 200.0 / (te + 100.0) 380 381 # Catch invalid widths. 382 if width <= 0.0: 383 width = 0.001 384 385 # Colour value (hyperbolic). 386 colour_value = 1.0 / (te / 100.0 + 1.0) 387 388 # Catch invalid colours. 389 if colour_value < 0.0: 390 colour_value = 0.0 391 elif colour_value > 1.0: 392 colour_value = 1.0 393 394 # Default colours. 395 if colour_start == None: 396 colour_start = 'turquoise' 397 if colour_end == None: 398 colour_end = 'blue' 399 400 # Get the RGB colour array (swap the colours because of the inverted hyperbolic colour value). 401 rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list) 402 403 # Colour the peptide bond. 404 self.classic_colour(res_num, width, rgb_array)
405 406
407 - def classic_order_param(self, res_num, s2, colour_start, colour_end, colour_list):
408 """Function for generating the bond width and colours for order parameters.""" 409 410 # The bond width (aiming for a width range of 2 to 0 for S2 values of 0.0 to 1.0). 411 if s2 <= 0.0: 412 width = 2.0 413 else: 414 width = 2.0 * (1.0 - s2**2) 415 416 # Catch invalid widths. 417 if width <= 0.0: 418 width = 0.001 419 420 # Colour value (quartic). 421 colour_value = s2 ** 4 422 423 # Catch invalid colours. 424 if colour_value < 0.0: 425 colour_value = 0.0 426 elif colour_value > 1.0: 427 colour_value = 1.0 428 429 # Default colours. 430 if colour_start == None: 431 colour_start = 'red' 432 if colour_end == None: 433 colour_end = 'yellow' 434 435 # Get the RGB colour array. 436 rgb_array = linear_gradient(colour_value, colour_start, colour_end, colour_list) 437 438 # Colour the peptide bond. 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 # The Rex value at the first field strength. 446 rex = rex * (2.0 * pi * cdp.frq[cdp.ri_ids[0]])**2 447 448 # The bond width (aiming for a width range of 2 to 0 for Rex values of 0 to 25 s^-1). 449 width = 2.0 - 2.0 / (rex/5.0 + 1.0) 450 451 # Catch invalid widths. 452 if width <= 0.0: 453 width = 0.001 454 455 # Colour value (hyperbolic). 456 colour_value = 1.0 / (rex + 1.0) 457 458 # Catch invalid colours. 459 if colour_value < 0.0: 460 colour_value = 0.0 461 elif colour_value > 1.0: 462 colour_value = 1.0 463 464 # Default colours. 465 if colour_start == None: 466 colour_start = 'yellow' 467 if colour_end == None: 468 colour_end = 'red' 469 470 # Get the RGB colour array (swap the colours because of the inverted hyperbolic colour value). 471 rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list) 472 473 # Colour the peptide bond. 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 # Initialise. 495 self.commands = [] 496 497 # The classic style. 498 if style == 'classic': 499 self.classic_style(data_type, colour_start, colour_end, colour_list, spin_id) 500 501 # Unknown style. 502 else: 503 raise RelaxStyleError(style) 504 505 # Return the command array. 506 return self.commands
507