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 (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program 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 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """The module containing the base class for the model-free macros.""" 
 24   
 25  # Python module imports. 
 26  from math import pi 
 27  from re import search 
 28   
 29  # relax module imports. 
 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   
38 -class Macro:
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 # Generate the macro header. 77 ############################ 78 79 self.classic_header() 80 81 82 # S2. 83 ##### 84 85 if data_type == 's2': 86 # Loop over the spins. 87 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 88 # Skip deselected spins. 89 if not spin.select: 90 continue 91 92 # Skip spins which don't have an S2 value. 93 if not hasattr(spin, 's2') or spin.s2 == None: 94 continue 95 96 # S2 width and colour for the backbone NH. 97 if spin.name == 'N': 98 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 99 100 101 # S2f. 102 ###### 103 104 elif data_type == 's2f': 105 # Loop over the spins. 106 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 107 # Skip deselected spins. 108 if not spin.select: 109 continue 110 111 # The backbone NH. 112 if spin.name == 'N': 113 # Colour residues which don't have an S2f value white. 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 # S2f width and colour. 118 else: 119 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list) 120 121 122 # S2s. 123 ###### 124 125 elif data_type == 's2s': 126 # Loop over the spins. 127 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 128 # Skip deselected spins. 129 if not spin.select: 130 continue 131 132 # The backbone NH. 133 if spin.name == 'N': 134 # Colour residues which don't have an S2s value white. 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 # S2s width and colour. 139 else: 140 self.classic_order_param(res_num, spin.s2s, colour_start, colour_end, colour_list) 141 142 143 # Amplitude of fast motions. 144 ############################ 145 146 elif data_type == 'amp_fast': 147 # Loop over the spins. 148 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 149 # Skip deselected spins. 150 if not spin.select: 151 continue 152 153 # The model. 154 if search('tm[0-9]', spin.model): 155 model = spin.model[1:] 156 else: 157 model = spin.model 158 159 # The backbone NH. 160 if spin.name == 'N': 161 # S2f width and colour (for models m5 to m8). 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 # S2 width and colour (for models m1 and m3). 166 elif model == 'm1' or model == 'm3': 167 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 168 169 # S2 width and colour (for models m2 and m4 when te <= 200 ps). 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 # White bonds (for models m2 and m4 when te > 200 ps). 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 # Catch errors. 178 else: 179 raise RelaxFault 180 181 182 # Amplitude of slow motions. 183 ############################ 184 185 elif data_type == 'amp_slow': 186 # Loop over the spins. 187 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 188 # Skip deselected spins. 189 if not spin.select: 190 continue 191 192 # The model. 193 if search('tm[0-9]', spin.model): 194 model = spin.model[1:] 195 else: 196 model = spin.model 197 198 # The backbone NH. 199 if spin.name == 'N': 200 # S2 width and colour (for models m5 to m8). 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 # S2 width and colour (for models m2 and m4 when te > 200 ps). 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 # White bonds for fast motions. 209 else: 210 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 211 212 # te. 213 ##### 214 215 elif data_type == 'te': 216 # Loop over the spins. 217 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 218 # Skip deselected spins. 219 if not spin.select: 220 continue 221 222 # Skip spins which don't have a te value. 223 if not hasattr(spin, 'te') or spin.te == None: 224 continue 225 226 # te width and colour (backbone NH). 227 if spin.name == 'N': 228 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list) 229 230 231 # tf. 232 ##### 233 234 elif data_type == 'tf': 235 # Loop over the spins. 236 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 237 # Skip deselected spins. 238 if not spin.select: 239 continue 240 241 # Skip spins which don't have a tf value. 242 if not hasattr(spin, 'tf') or spin.tf == None: 243 continue 244 245 # tf width and colour (backbone NH). 246 if spin.name == 'N': 247 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list) 248 249 250 # ts. 251 ##### 252 253 elif data_type == 'ts': 254 # Loop over the spins. 255 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 256 # Skip deselected spins. 257 if not spin.select: 258 continue 259 260 # Skip spins which don't have a ts value. 261 if not hasattr(spin, 'ts') or spin.ts == None: 262 continue 263 264 # The default start and end colours. 265 if colour_start == None: 266 colour_start = 'blue' 267 if colour_end == None: 268 colour_end = 'black' 269 270 # ts width and colour (backbone NH). 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 # Timescale of fast motions. 276 ############################ 277 278 elif data_type == 'time_fast': 279 # Loop over the spins. 280 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 281 # Skip deselected spins. 282 if not spin.select: 283 continue 284 285 # The model. 286 if search('tm[0-9]', spin.model): 287 model = spin.model[1:] 288 else: 289 model = spin.model 290 291 # The backbone NH. 292 if spin.name == 'N': 293 # tf width and colour (for models m5 to m8). 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 # te width and colour (for models m2 and m4 when te <= 200 ps). 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 # All other residues are assumed to have a fast correlation time of zero (statistically zero, not real zero!). 302 # Colour these bonds white. 303 else: 304 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 305 306 307 # Timescale of slow motions. 308 ############################ 309 310 elif data_type == 'time_slow': 311 # Loop over the spins. 312 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 313 # Skip deselected spins. 314 if not spin.select: 315 continue 316 317 # The model. 318 if search('tm[0-9]', spin.model): 319 model = spin.model[1:] 320 else: 321 model = spin.model 322 323 # The default start and end colours. 324 if colour_start == None: 325 colour_start = 'blue' 326 if colour_end == None: 327 colour_end = 'black' 328 329 # The backbone NH. 330 if spin.name == 'N': 331 # ts width and colour (for models m5 to m8). 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 # te width and colour (for models m2 and m4 when te > 200 ps). 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 # White bonds for the rest. 340 else: 341 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 342 343 344 # Rex. 345 ###### 346 347 elif data_type == 'rex': 348 # Loop over the spins. 349 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 350 # Skip deselected spins. 351 if not spin.select: 352 continue 353 354 # The backbone NH. 355 if spin.name == 'N': 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