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

Source Code for Module specific_analyses.model_free.macro_base

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2014 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 Molmol and Pymol base macro methods of the specific API for model-free analysis.""" 
 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 lib.errors import RelaxError, RelaxStyleError, RelaxUnknownDataTypeError 
 32  from pipe_control.mol_res_spin import spin_loop 
 33   
 34   
 35   
36 -class Macro:
37 """The base class for the model-free analysis Molmol and PyMOL macro creation.""" 38
39 - def classic_style(self, data_type=None, colour_start=None, colour_end=None, colour_list=None, spin_id=None):
40 """The classic macro style. 41 42 @keyword data_type: The parameter name or data type. 43 @type data_type: str 44 @keyword colour_start: The starting colour (must be a MOLMOL or X11 name). 45 @type colour_start: str 46 @keyword colour_end: The ending colour (must be a MOLMOL or X11 name). 47 @type colour_end: str 48 @keyword colour_list: The colour list used, either 'molmol' or 'x11'. 49 @type colour_list: str 50 @keyword spin_id: The spin identification string. 51 @type spin_id: str 52 """ 53 54 # Generate the macro header. 55 ############################ 56 57 self.classic_header() 58 59 60 # S2. 61 ##### 62 63 if data_type == 's2': 64 # Loop over the spins. 65 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 66 # Skip deselected spins or spins with no model information set. 67 if not spin.select or not hasattr(spin, 'model'): 68 continue 69 70 # Skip spins which don't have an S2 value. 71 if not hasattr(spin, 's2') or spin.s2 == None: 72 continue 73 74 # S2 width and colour for the backbone NH. 75 if spin.name == 'N': 76 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 77 78 79 # S2f. 80 ###### 81 82 elif data_type == 's2f': 83 # Loop over the spins. 84 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 85 # Skip deselected spins or spins with no model information set. 86 if not spin.select or not hasattr(spin, 'model'): 87 continue 88 89 # The backbone NH. 90 if spin.name == 'N': 91 # Colour residues which don't have an S2f value white. 92 if not hasattr(spin, 's2f') or spin.s2f == None: 93 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 94 95 # S2f width and colour. 96 else: 97 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list) 98 99 100 # S2s. 101 ###### 102 103 elif data_type == 's2s': 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 or spins with no model information set. 107 if not spin.select or not hasattr(spin, 'model'): 108 continue 109 110 # The backbone NH. 111 if spin.name == 'N': 112 # Colour residues which don't have an S2s value white. 113 if not hasattr(spin, 's2s') or spin.s2s == None: 114 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 115 116 # S2s width and colour. 117 else: 118 self.classic_order_param(res_num, spin.s2s, colour_start, colour_end, colour_list) 119 120 121 # Amplitude of fast motions. 122 ############################ 123 124 elif data_type == 'amp_fast': 125 # Loop over the spins. 126 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 127 # Skip deselected spins or spins with no model information set. 128 if not spin.select or not hasattr(spin, 'model'): 129 continue 130 131 # The model. 132 if search('tm[0-9]', spin.model): 133 model = spin.model[1:] 134 else: 135 model = spin.model 136 137 # The backbone NH. 138 if spin.name == 'N': 139 # S2f width and colour (for models m5 to m8). 140 if hasattr(spin, 's2f') and spin.s2f != None: 141 self.classic_order_param(res_num, spin.s2f, colour_start, colour_end, colour_list) 142 143 # S2 width and colour (for models m1 and m3). 144 elif model == 'm1' or model == 'm3': 145 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 146 147 # S2 width and colour (for models m2 and m4 when te <= 200 ps). 148 elif (model == 'm2' or model == 'm4') and spin.te <= 200e-12: 149 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 150 151 # White bonds (for models m2 and m4 when te > 200 ps). 152 elif (model == 'm2' or model == 'm4') and spin.te > 200e-12: 153 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 154 155 156 # Amplitude of slow motions. 157 ############################ 158 159 elif data_type == 'amp_slow': 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 or spins with no model information set. 163 if not spin.select or not hasattr(spin, 'model'): 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 # The backbone NH. 173 if spin.name == 'N': 174 # S2 width and colour (for models m5 to m8). 175 if hasattr(spin, 'ts') and spin.ts != None: 176 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 177 178 # S2 width and colour (for models m2 and m4 when te > 200 ps). 179 elif (model == 'm2' or model == 'm4') and spin.te > 200 * 1e-12: 180 self.classic_order_param(res_num, spin.s2, colour_start, colour_end, colour_list) 181 182 # White bonds for fast motions. 183 else: 184 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 185 186 # te. 187 ##### 188 189 elif data_type == 'te': 190 # Loop over the spins. 191 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 192 # Skip deselected spins or spins with no model information set. 193 if not spin.select or not hasattr(spin, 'model'): 194 continue 195 196 # Skip spins which don't have a te value. 197 if not hasattr(spin, 'te') or spin.te == None: 198 continue 199 200 # te width and colour (backbone NH). 201 if spin.name == 'N': 202 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list) 203 204 205 # tf. 206 ##### 207 208 elif data_type == 'tf': 209 # Loop over the spins. 210 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 211 # Skip deselected spins or spins with no model information set. 212 if not spin.select or not hasattr(spin, 'model'): 213 continue 214 215 # Skip spins which don't have a tf value. 216 if not hasattr(spin, 'tf') or spin.tf == None: 217 continue 218 219 # tf width and colour (backbone NH). 220 if spin.name == 'N': 221 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list) 222 223 224 # ts. 225 ##### 226 227 elif data_type == 'ts': 228 # Loop over the spins. 229 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 230 # Skip deselected spins or spins with no model information set. 231 if not spin.select or not hasattr(spin, 'model'): 232 continue 233 234 # Skip spins which don't have a ts value. 235 if not hasattr(spin, 'ts') or spin.ts == None: 236 continue 237 238 # The default start and end colours. 239 if colour_start == None: 240 colour_start = 'blue' 241 if colour_end == None: 242 colour_end = 'black' 243 244 # ts width and colour (backbone NH). 245 if spin.name == 'N': 246 self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list) 247 248 249 # Timescale of fast motions. 250 ############################ 251 252 elif data_type == 'time_fast': 253 # Loop over the spins. 254 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 255 # Skip deselected spins or spins with no model information set. 256 if not spin.select or not hasattr(spin, 'model'): 257 continue 258 259 # The model. 260 if search('tm[0-9]', spin.model): 261 model = spin.model[1:] 262 else: 263 model = spin.model 264 265 # The backbone NH. 266 if spin.name == 'N': 267 # tf width and colour (for models m5 to m8). 268 if hasattr(spin, 'tf') and spin.tf != None: 269 self.classic_correlation_time(res_num, spin.tf, colour_start, colour_end, colour_list) 270 271 # te width and colour (for models m2 and m4 when te <= 200 ps). 272 elif (model == 'm2' or model == 'm4') and spin.te <= 200e-12: 273 self.classic_correlation_time(res_num, spin.te, colour_start, colour_end, colour_list) 274 275 # All other residues are assumed to have a fast correlation time of zero (statistically zero, not real zero!). 276 # Colour these bonds white. 277 else: 278 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 279 280 281 # Timescale of slow motions. 282 ############################ 283 284 elif data_type == 'time_slow': 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 or spins with no model information set. 288 if not spin.select or not hasattr(spin, 'model'): 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 # The default start and end colours. 298 if colour_start == None: 299 colour_start = 'blue' 300 if colour_end == None: 301 colour_end = 'black' 302 303 # The backbone NH. 304 if spin.name == 'N': 305 # ts width and colour (for models m5 to m8). 306 if hasattr(spin, 'ts') and spin.ts != None: 307 self.classic_correlation_time(res_num, spin.ts / 10.0, colour_start, colour_end, colour_list) 308 309 # te width and colour (for models m2 and m4 when te > 200 ps). 310 elif (model == 'm2' or model == 'm4') and spin.te > 200e-12: 311 self.classic_correlation_time(res_num, spin.te / 10.0, colour_start, colour_end, colour_list) 312 313 # White bonds for the rest. 314 else: 315 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 316 317 318 # Rex. 319 ###### 320 321 elif data_type == 'rex': 322 # Loop over the spins. 323 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True): 324 # Skip deselected spins or spins with no model information set. 325 if not spin.select or not hasattr(spin, 'model'): 326 continue 327 328 # The backbone NH. 329 if spin.name == 'N': 330 # Residues which chemical exchange. 331 if hasattr(spin, 'rex') and spin.rex != None: 332 self.classic_rex(res_num, spin.rex, colour_start, colour_end, colour_list) 333 334 # White bonds for the rest. 335 else: 336 self.classic_colour(res_num=res_num, width=0.3, rgb_array=[1, 1, 1]) 337 338 339 # Unknown data type. 340 #################### 341 342 else: 343 raise RelaxUnknownDataTypeError(data_type)
344 345
346 - def classic_correlation_time(self, res_num, te, colour_start, colour_end, colour_list):
347 """Function for generating the bond width and colours for correlation times.""" 348 349 # The te value in picoseconds. 350 te = te * 1e12 351 352 # The bond width (aiming for a width range of 2 to 0 for te values of 0 to 10 ns). 353 width = 2.0 - 200.0 / (te + 100.0) 354 355 # Catch invalid widths. 356 if width <= 0.0: 357 width = 0.001 358 359 # Colour value (hyperbolic). 360 colour_value = 1.0 / (te / 100.0 + 1.0) 361 362 # Catch invalid colours. 363 if colour_value < 0.0: 364 colour_value = 0.0 365 elif colour_value > 1.0: 366 colour_value = 1.0 367 368 # Default colours. 369 if colour_start == None: 370 colour_start = 'turquoise' 371 if colour_end == None: 372 colour_end = 'blue' 373 374 # Get the RGB colour array (swap the colours because of the inverted hyperbolic colour value). 375 rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list) 376 377 # Colour the peptide bond. 378 self.classic_colour(res_num, width, rgb_array)
379 380
381 - def classic_order_param(self, res_num, s2, colour_start, colour_end, colour_list):
382 """Function for generating the bond width and colours for order parameters.""" 383 384 # The bond width (aiming for a width range of 2 to 0 for S2 values of 0.0 to 1.0). 385 if s2 <= 0.0: 386 width = 2.0 387 else: 388 width = 2.0 * (1.0 - s2**2) 389 390 # Catch invalid widths. 391 if width <= 0.0: 392 width = 0.001 393 394 # Colour value (quartic). 395 colour_value = s2 ** 4 396 397 # Catch invalid colours. 398 if colour_value < 0.0: 399 colour_value = 0.0 400 elif colour_value > 1.0: 401 colour_value = 1.0 402 403 # Default colours. 404 if colour_start == None: 405 colour_start = 'red' 406 if colour_end == None: 407 colour_end = 'yellow' 408 409 # Get the RGB colour array. 410 rgb_array = linear_gradient(colour_value, colour_start, colour_end, colour_list) 411 412 # Colour the peptide bond. 413 self.classic_colour(res_num, width, rgb_array)
414 415
416 - def classic_rex(self, res_num, rex, colour_start, colour_end, colour_list):
417 """Function for generating the bond width and colours for correlation times.""" 418 419 # The 1st spectrometer frequency. 420 if not hasattr(cdp, 'spectrometer_frq'): 421 raise RelaxError("No spectrometer frequency information is present in the current data pipe.") 422 if hasattr(cdp, 'ri_ids'): 423 frq = cdp.spectrometer_frq[cdp.ri_ids[0]] 424 else: # Take the highest frequency, if all else fails. 425 frqs = sorted(cdp.spectrometer_frq.values()) 426 frq = frqs[-1] 427 428 # The Rex value. 429 rex = rex * (2.0 * pi * frq)**2 430 431 # The bond width (aiming for a width range of 2 to 0 for Rex values of 0 to 25 s^-1). 432 width = 2.0 - 2.0 / (rex/5.0 + 1.0) 433 434 # Catch invalid widths. 435 if width <= 0.0: 436 width = 0.001 437 438 # Colour value (hyperbolic). 439 colour_value = 1.0 / (rex + 1.0) 440 441 # Catch invalid colours. 442 if colour_value < 0.0: 443 colour_value = 0.0 444 elif colour_value > 1.0: 445 colour_value = 1.0 446 447 # Default colours. 448 if colour_start == None: 449 colour_start = 'yellow' 450 if colour_end == None: 451 colour_end = 'red' 452 453 # Get the RGB colour array (swap the colours because of the inverted hyperbolic colour value). 454 rgb_array = linear_gradient(colour_value, colour_end, colour_start, colour_list) 455 456 # Colour the peptide bond. 457 self.classic_colour(res_num, width, rgb_array)
458 459
460 - def create_macro(self, data_type, style=None, colour_start=None, colour_end=None, colour_list=None, spin_id=None):
461 """Create and return an array of macros of the model-free parameters. 462 463 @param data_type: The parameter name or data type. 464 @type data_type: str 465 @keyword style: The Molmol style. 466 @type style: None or str 467 @keyword colour_start: The starting colour (must be a MOLMOL or X11 name). 468 @type colour_start: str 469 @keyword colour_end: The ending colour (must be a MOLMOL or X11 name). 470 @type colour_end: str 471 @keyword colour_list: The colour list used, either 'molmol' or 'x11'. 472 @type colour_list: str 473 @keyword spin_id: The spin identification string. 474 @type spin_id: str 475 """ 476 477 # Initialise. 478 self.commands = [] 479 480 # The classic style. 481 if style == 'classic': 482 self.classic_style(data_type, colour_start, colour_end, colour_list, spin_id) 483 484 # Unknown style. 485 else: 486 raise RelaxStyleError(style) 487 488 # Return the command array. 489 return self.commands
490