Package generic_fns :: Module pymol_control
[hide private]
[frames] | no frames]

Source Code for Module generic_fns.pymol_control

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2006-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  """Module for interfacing with PyMOL.""" 
 24   
 25  # Dependency check module. 
 26  import dep_check 
 27   
 28  # Python module imports. 
 29  if dep_check.pymol_module: 
 30      import pymol 
 31  from math import pi 
 32  from numpy import float64, transpose, zeros 
 33  from os import sep 
 34  PIPE, Popen = None, None 
 35  if dep_check.subprocess_module: 
 36      from subprocess import PIPE, Popen 
 37  from tempfile import mktemp 
 38  from time import sleep 
 39   
 40  # relax module imports. 
 41  from generic_fns.mol_res_spin import exists_mol_res_spin_data 
 42  from generic_fns import pipes 
 43  from generic_fns.result_files import add_result_file 
 44  from maths_fns.rotation_matrix import euler_to_R_zyz, R_to_axis_angle 
 45  from relax_errors import RelaxError, RelaxNoPdbError, RelaxNoSequenceError 
 46  from relax_io import delete, file_root, get_file_path, open_read_file, open_write_file, test_binary 
 47  from specific_fns.setup import get_specific_fn 
 48  from status import Status; status = Status() 
 49   
 50   
51 -class Pymol:
52 """The PyMOL execution object.""" 53
54 - def __init__(self, exec_mode=None):
55 """Set up the PyMOL execution object. 56 57 @keyword exec_mode: The execution mode which can be either 'module' or 'external'. 58 @type exec_mode: None or str 59 """ 60 61 # Variable for storing the pymol command history. 62 self.command_history = "" 63 64 # The pymol mode of operation. 65 self.exec_mode = exec_mode 66 if not exec_mode: 67 if dep_check.pymol_module: 68 self.exec_mode = 'module' 69 self.open = False 70 else: 71 self.exec_mode = 'external'
72 73
74 - def clear_history(self):
75 """Clear the PyMOL command history.""" 76 77 self.command_history = ""
78 79
80 - def exec_cmd(self, command=None, store_command=True):
81 """Execute a PyMOL command. 82 83 @param command: The PyMOL command to send into the program. 84 @type command: str 85 @param store_command: A flag specifying if the command should be stored in the history 86 variable. 87 @type store_command: bool 88 """ 89 90 # Reopen the GUI if needed. 91 if not self.running(): 92 self.open_gui() 93 94 # Execute the command. 95 if self.exec_mode == 'module': 96 pymol.cmd.do(command) 97 else: 98 self.pymol.write(command + '\n') 99 100 # Place the command in the command history. 101 if store_command: 102 self.command_history = self.command_history + command + "\n"
103 104
105 - def open_gui(self):
106 """Open the PyMOL GUI.""" 107 108 # Use the PyMOL python modules. 109 if self.exec_mode == 'module': 110 # Open the GUI. 111 pymol.finish_launching() 112 self.open = True 113 114 # Otherwise execute PyMOL on the command line. 115 if self.exec_mode == 'external': 116 # Test that the PyMOL binary exists. 117 test_binary('pymol') 118 119 # Python 2.3 and earlier. 120 if Popen == None: 121 raise RelaxError("The subprocess module is not available in this version of Python.") 122 123 # Open PyMOL as a pipe. 124 self.pymol = Popen(['pymol', '-qpK'], stdin=PIPE).stdin 125 126 # Execute the command history. 127 if len(self.command_history) > 0: 128 self.exec_cmd(self.command_history, store_command=0) 129 return 130 131 # Test if the PDB file has been loaded. 132 if hasattr(cdp, 'structure'): 133 self.open_pdb()
134 135
136 - def open_pdb(self):
137 """Open the PDB file in PyMOL.""" 138 139 # Test if PyMOL is running. 140 if not self.running(): 141 return 142 143 # Reinitialise PyMOL. 144 self.exec_cmd("reinitialize") 145 146 # Open the PDB files. 147 open_files = [] 148 for model in cdp.structure.structural_data: 149 for mol in model.mol: 150 # The file path. 151 file = mol.file_name 152 if mol.file_path: 153 file = mol.file_path + sep + file 154 155 # Already loaded. 156 if file in open_files: 157 continue 158 159 # Open the file in PyMOL. 160 self.exec_cmd("load " + file) 161 162 # Add to the open file list. 163 open_files.append(file)
164 165
166 - def running(self):
167 """Test if PyMOL is running. 168 169 @return: Whether the Molmol pipe is open or not. 170 @rtype: bool 171 """ 172 173 # Test if PyMOL module interface is already running. 174 if self.exec_mode == 'module': 175 return self.open 176 177 # Test if command line PyMOL is already running. 178 if self.exec_mode == 'external': 179 # Pipe exists. 180 if not hasattr(self, 'pymol'): 181 return False 182 183 # Test if the pipe has been broken. 184 try: 185 self.pymol.write('\n') 186 except IOError: 187 return False 188 189 # PyMOL is running. 190 return True
191 192 193 194 # Initialise the Pymol executable object. 195 pymol_obj = Pymol('external') 196 """Pymol data container instance.""" 197 198 199
200 -def cartoon():
201 """Apply the PyMOL cartoon style and colour by secondary structure.""" 202 203 # Test if the current data pipe exists. 204 pipes.test() 205 206 # Test for the structure. 207 if not hasattr(cdp, 'structure'): 208 raise RelaxNoPdbError 209 210 # Loop over the PDB files. 211 open_files = [] 212 for model in cdp.structure.structural_data: 213 for mol in model.mol: 214 # Identifier. 215 pdb_file = mol.file_name 216 if mol.file_path: 217 pdb_file = mol.file_path + sep + pdb_file 218 id = file_root(pdb_file) 219 220 # Already loaded. 221 if pdb_file in open_files: 222 continue 223 224 # Add to the open file list. 225 open_files.append(pdb_file) 226 227 # Hide everything. 228 pymol_obj.exec_cmd("cmd.hide('everything'," + repr(id) + ")") 229 230 # Show the cartoon style. 231 pymol_obj.exec_cmd("cmd.show('cartoon'," + repr(id) + ")") 232 233 # Colour by secondary structure. 234 pymol_obj.exec_cmd("util.cbss(" + repr(id) + ", 'red', 'yellow', 'green')")
235 236
237 -def command(command):
238 """Function for sending PyMOL commands to the program pipe. 239 240 @param command: The command to send into the program. 241 @type command: str 242 """ 243 244 # Pass the command to PyMOL. 245 pymol_obj.exec_cmd(command)
246 247
248 -def cone_pdb(file=None):
249 """Display the cone geometric object. 250 251 @keyword file: The name of the file containing the cone geometric object. 252 @type file: str 253 """ 254 255 # Read in the cone PDB file. 256 pymol_obj.exec_cmd("load " + file) 257 258 259 # The cone axes. 260 ################ 261 262 # Select the AVE, XAX, YAX, ZAX, and SIM residues. 263 pymol_obj.exec_cmd("select (resn AVE,XAX,YAX,ZAX,SIM)") 264 265 # Show the vector as a stick. 266 pymol_obj.exec_cmd("show stick, 'sele'") 267 268 # Colour it blue. 269 pymol_obj.exec_cmd("color cyan, 'sele'") 270 271 # Select the atom used for labelling. 272 pymol_obj.exec_cmd("select (resn AVE,XAX,YAX,ZAX,SIM and symbol N)") 273 274 # Hide the atom. 275 pymol_obj.exec_cmd("hide ('sele')") 276 277 # Label using the atom name. 278 pymol_obj.exec_cmd("cmd.label(\"sele\",\"name\")") 279 280 281 # The cone object. 282 ################## 283 284 # Select the CON residue. 285 pymol_obj.exec_cmd("select (resn CON,EDG)") 286 287 # Hide everything. 288 pymol_obj.exec_cmd("hide ('sele')") 289 290 # Show as 'sticks'. 291 pymol_obj.exec_cmd("show sticks, 'sele'") 292 293 # Colour it white. 294 pymol_obj.exec_cmd("color white, 'sele'") 295 296 # Shorten the stick width from 0.25 to 0.15. 297 pymol_obj.exec_cmd("set stick_radius,0.15000") 298 299 # Set a bit of transparency. 300 pymol_obj.exec_cmd("set stick_transparency, 0.3") 301 302 303 # Clean up. 304 ########### 305 306 # Remove the selection. 307 pymol_obj.exec_cmd("cmd.delete('sele')") 308 309 310 # Rotate to the average position. 311 ################################# 312 313 # Check if there is an average position. 314 if hasattr(cdp, 'ave_pos_beta'): 315 # The average position rotation. 316 ave_pos_R = zeros((3, 3), float64) 317 ave_pos_alpha = 0.0 318 if hasattr(cdp, 'ave_pos_alpha') and cdp.ave_pos_alpha != None: 319 ave_pos_alpha = cdp.ave_pos_alpha 320 euler_to_R_zyz(ave_pos_alpha, cdp.ave_pos_beta, cdp.ave_pos_gamma, ave_pos_R) 321 322 # The rotation is passive (need to rotated the moving domain back into the average position defined in the non-moving domain PDB frame). 323 R = transpose(ave_pos_R) 324 325 # Convert to axis-angle notation. 326 axis, angle = R_to_axis_angle(R) 327 328 # The PDB file to rotate. 329 for i in range(len(cdp.domain_to_pdb)): 330 if cdp.domain_to_pdb[i][0] != cdp.ref_domain: 331 pdb = cdp.domain_to_pdb[i][1] 332 333 # Execute the pymol command to rotate. 334 pymol_obj.exec_cmd("cmd.rotate([%s, %s, %s], %s, '%s', origin=[%s, %s, %s])" % (axis[0], axis[1], axis[2], angle/pi*180.0, pdb, cdp.pivot[0], cdp.pivot[1], cdp.pivot[2]))
335 336
337 -def create_macro(data_type=None, style="classic", colour_start=None, colour_end=None, colour_list=None):
338 """Create an array of PyMOL commands. 339 340 @keyword data_type: The data type to map to the structure. 341 @type data_type: str 342 @keyword style: The style of the macro. 343 @type style: str 344 @keyword colour_start: The starting colour of the linear gradient. 345 @type colour_start: str or RBG colour array (len 3 with vals from 0 to 1) 346 @keyword colour_end: The ending colour of the linear gradient. 347 @type colour_end: str or RBG colour array (len 3 with vals from 0 to 1) 348 @keyword colour_list: The colour list to search for the colour names. Can be either 'molmol' or 'x11'. 349 @type colour_list: str or None 350 @return: The list of PyMOL commands. 351 @rtype: list of str 352 """ 353 354 # Specific PyMOL macro creation function. 355 macro = get_specific_fn('pymol_macro', cdp.pipe_type) 356 357 # Get the macro. 358 commands = macro(data_type, style, colour_start, colour_end, colour_list) 359 360 # Return the macro commands. 361 return commands
362 363
364 -def macro_apply(data_type=None, style="classic", colour_start_name=None, colour_start_rgb=None, colour_end_name=None, colour_end_rgb=None, colour_list=None):
365 """Execute a PyMOL macro. 366 367 @keyword data_type: The data type to map to the structure. 368 @type data_type: str 369 @keyword style: The style of the macro. 370 @type style: str 371 @keyword colour_start_name: The name of the starting colour of the linear gradient. 372 @type colour_start_name: str 373 @keyword colour_start_rgb: The RGB array starting colour of the linear gradient. 374 @type colour_start_rgb: RBG colour array (len 3 with vals from 0 to 1) 375 @keyword colour_end_name: The name of the ending colour of the linear gradient. 376 @type colour_end_name: str 377 @keyword colour_end_rgb: The RGB array ending colour of the linear gradient. 378 @type colour_end_rgb: RBG colour array (len 3 with vals from 0 to 1) 379 @keyword colour_list: The colour list to search for the colour names. Can be either 'molmol' or 'x11'. 380 @type colour_list: str or None 381 """ 382 383 # Test if the current data pipe exists. 384 pipes.test() 385 386 # Test if sequence data exists. 387 if not exists_mol_res_spin_data(): 388 raise RelaxNoSequenceError 389 390 # Check the arguments. 391 if colour_start_name != None and colour_start_rgb != None: 392 raise RelaxError("The starting colour name and RGB colour array cannot both be supplied.") 393 if colour_end_name != None and colour_end_rgb != None: 394 raise RelaxError("The ending colour name and RGB colour array cannot both be supplied.") 395 396 # Merge the colour args. 397 if colour_start_name != None: 398 colour_start = colour_start_name 399 else: 400 colour_start = colour_start_rgb 401 if colour_end_name != None: 402 colour_end = colour_end_name 403 else: 404 colour_end = colour_end_rgb 405 406 # Clear the PyMOL history first. 407 pymol_obj.clear_history() 408 409 # Create the macro. 410 commands = create_macro(data_type=data_type, style=style, colour_start=colour_start, colour_end=colour_end, colour_list=colour_list) 411 412 # Save the commands as a temporary file, execute it, then delete it. 413 try: 414 # Temp file name. 415 tmpfile = "%s.pml" % mktemp() 416 417 # Open the file. 418 file = open(tmpfile, 'w') 419 420 # Loop over the commands and write them. 421 for command in commands: 422 file.write("%s\n" % command) 423 file.close() 424 425 # Execute the macro. 426 pymol_obj.exec_cmd("@%s" % tmpfile) 427 428 # Wait a bit for PyMOL to catch up (it takes time for PyMOL to start and the macro to execute). 429 sleep(3) 430 431 # Delete the temporary file (no matter what). 432 finally: 433 # Delete the file. 434 delete(tmpfile, fail=False)
435 436
437 -def macro_run(file=None, dir=None):
438 """Execute the PyMOL macro from the given text file. 439 440 @keyword file: The name of the macro file to execute. 441 @type file: str 442 @keyword dir: The name of the directory where the macro file is located. 443 @type dir: str 444 """ 445 446 # Open the file for reading. 447 file_path = get_file_path(file, dir) 448 file = open_read_file(file, dir) 449 450 # Loop over the commands and apply them. 451 for command in file.readlines(): 452 pymol_obj.exec_cmd(command)
453 454
455 -def macro_write(data_type=None, style="classic", colour_start_name=None, colour_start_rgb=None, colour_end_name=None, colour_end_rgb=None, colour_list=None, file=None, dir=None, force=False):
456 """Create a PyMOL macro file. 457 458 @keyword data_type: The data type to map to the structure. 459 @type data_type: str 460 @keyword style: The style of the macro. 461 @type style: str 462 @keyword colour_start_name: The name of the starting colour of the linear gradient. 463 @type colour_start_name: str 464 @keyword colour_start_rgb: The RGB array starting colour of the linear gradient. 465 @type colour_start_rgb: RBG colour array (len 3 with vals from 0 to 1) 466 @keyword colour_end_name: The name of the ending colour of the linear gradient. 467 @type colour_end_name: str 468 @keyword colour_end_rgb: The RGB array ending colour of the linear gradient. 469 @type colour_end_rgb: RBG colour array (len 3 with vals from 0 to 1) 470 @keyword colour_list: The colour list to search for the colour names. Can be either 'molmol' or 'x11'. 471 @type colour_list: str or None 472 @keyword file: The name of the macro file to create. 473 @type file: str 474 @keyword dir: The name of the directory to place the macro file into. 475 @type dir: str 476 @keyword force: Flag which if set to True will cause any pre-existing file to be overwritten. 477 @type force: bool 478 """ 479 480 # Test if the current data pipe exists. 481 pipes.test() 482 483 # Test if sequence data exists. 484 if not exists_mol_res_spin_data(): 485 raise RelaxNoSequenceError 486 487 # Check the arguments. 488 if colour_start_name != None and colour_start_rgb != None: 489 raise RelaxError("The starting colour name and RGB colour array cannot both be supplied.") 490 if colour_end_name != None and colour_end_rgb != None: 491 raise RelaxError("The ending colour name and RGB colour array cannot both be supplied.") 492 493 # Merge the colour args. 494 if colour_start_name != None: 495 colour_start = colour_start_name 496 else: 497 colour_start = colour_start_rgb 498 if colour_end_name != None: 499 colour_end = colour_end_name 500 else: 501 colour_end = colour_end_rgb 502 503 # Create the macro. 504 commands = create_macro(data_type=data_type, style=style, colour_start=colour_start, colour_end=colour_end, colour_list=colour_list) 505 506 # File name. 507 if file == None: 508 file = data_type + '.pml' 509 510 # Open the file for writing. 511 file_path = get_file_path(file, dir) 512 file = open_write_file(file, dir, force) 513 514 # Loop over the commands and write them. 515 for command in commands: 516 file.write(command + "\n") 517 518 # Close the file. 519 file.close() 520 521 # Add the file to the results file list. 522 add_result_file(type='pymol', label='PyMOL', file=file_path)
523 524
525 -def tensor_pdb(file=None):
526 """Display the diffusion tensor geometric structure. 527 528 @keyword file: The name of the file containing the diffusion tensor geometric object. 529 @type file: str 530 """ 531 532 # Test if the current data pipe exists. 533 pipes.test() 534 535 # Read in the tensor PDB file. 536 pymol_obj.exec_cmd("load " + file) 537 538 539 # The tensor object. 540 #################### 541 542 # Select the TNS residue. 543 pymol_obj.exec_cmd("select resn TNS") 544 545 # Hide everything. 546 pymol_obj.exec_cmd("hide ('sele')") 547 548 # Show as 'sticks'. 549 pymol_obj.exec_cmd("show sticks, 'sele'") 550 551 552 # Centre of mass. 553 ################# 554 555 # Select the COM residue. 556 pymol_obj.exec_cmd("select resn COM") 557 558 # Show the centre of mass as the dots representation. 559 pymol_obj.exec_cmd("show dots, 'sele'") 560 561 # Colour it blue. 562 pymol_obj.exec_cmd("color blue, 'sele'") 563 564 565 # The diffusion tensor axes. 566 ############################ 567 568 # Select the AXS residue. 569 pymol_obj.exec_cmd("select resn AXS") 570 571 # Hide everything. 572 pymol_obj.exec_cmd("hide ('sele')") 573 574 # Show as 'sticks'. 575 pymol_obj.exec_cmd("show sticks, 'sele'") 576 577 # Colour it cyan. 578 pymol_obj.exec_cmd("color cyan, 'sele'") 579 580 # Select the N atoms of the AXS residue (used to display the axis labels). 581 pymol_obj.exec_cmd("select (resn AXS and elem N)") 582 583 # Label the atoms. 584 pymol_obj.exec_cmd("label 'sele', name") 585 586 587 588 # Monte Carlo simulations. 589 ########################## 590 591 # Select the SIM residue. 592 pymol_obj.exec_cmd("select resn SIM") 593 594 # Colour it. 595 pymol_obj.exec_cmd("colour cyan, 'sele'") 596 597 598 # Clean up. 599 ########### 600 601 # Remove the selection. 602 pymol_obj.exec_cmd("cmd.delete('sele')")
603 604
605 -def vector_dist(file=None):
606 """Display the XH bond vector distribution. 607 608 @keyword file: The vector distribution PDB file. 609 @type file: str 610 """ 611 612 # Test if the current data pipe exists. 613 pipes.test() 614 615 # The file root. 616 id = file_root(file) 617 618 # Read in the vector distribution PDB file. 619 pymol_obj.exec_cmd("load " + file) 620 621 622 # Create a surface. 623 ################### 624 625 # Select the vector distribution. 626 pymol_obj.exec_cmd("cmd.show('surface', " + repr(id) + ")")
627 628
629 -def view():
630 """Start PyMOL.""" 631 632 # Open PyMOL. 633 if pymol_obj.running(): 634 raise RelaxError("PyMOL is already running.") 635 else: 636 pymol_obj.open_gui()
637