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

Source Code for Module pipe_control.pymol_control

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2006-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  """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 F_OK, access, pardir, 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 lib.errors import RelaxError, RelaxNoPdbError, RelaxNoSequenceError 
 42  from lib.geometry.rotations import euler_to_R_zyz, R_to_axis_angle 
 43  from lib.io import delete, file_root, get_file_path, open_read_file, open_write_file, test_binary 
 44  from pipe_control import pipes 
 45  from pipe_control.mol_res_spin import exists_mol_res_spin_data 
 46  from pipe_control.result_files import add_result_file 
 47  from specific_analyses.api import return_api 
 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 as the current directory. 151 file_path = None 152 if access(mol.file_name, F_OK): 153 file_path = mol.file_name 154 155 # The file path using the relative path. 156 if file_path == None and hasattr(mol, 'file_path') and mol.file_path != None: 157 file_path = mol.file_path + sep + mol.file_name 158 if not access(file_path, F_OK): 159 file_path = None 160 161 # The file path using the absolute path. 162 if file_path == None and hasattr(mol, 'file_path_abs') and mol.file_path_abs != None: 163 file_path = mol.file_path_abs + sep + mol.file_name 164 if not access(file_path, F_OK): 165 file_path = None 166 167 # Hmmm, maybe the absolute path no longer exists and we are in a results subdirectory? 168 if file_path == None and hasattr(mol, 'file_path') and mol.file_path != None: 169 file_path = pardir + sep + mol.file_path + sep + mol.file_name 170 if not access(file_path, F_OK): 171 file_path = None 172 173 # Fall back to the current directory. 174 if file_path == None: 175 file_path = mol.file_name 176 177 # Already loaded. 178 if file_path in open_files: 179 continue 180 181 # Already loaded. 182 if file_path in open_files: 183 continue 184 185 # Open the file in PyMOL. 186 self.exec_cmd("load " + file_path) 187 188 # Add to the open file list. 189 open_files.append(file_path)
190 191
192 - def running(self):
193 """Test if PyMOL is running. 194 195 @return: Whether the Molmol pipe is open or not. 196 @rtype: bool 197 """ 198 199 # Test if PyMOL module interface is already running. 200 if self.exec_mode == 'module': 201 return self.open 202 203 # Test if command line PyMOL is already running. 204 if self.exec_mode == 'external': 205 # Pipe exists. 206 if not hasattr(self, 'pymol'): 207 return False 208 209 # Test if the pipe has been broken. 210 try: 211 self.pymol.write('\n') 212 except IOError: 213 return False 214 215 # PyMOL is running. 216 return True
217 218 219 220 # Initialise the Pymol executable object. 221 pymol_obj = Pymol('external') 222 """Pymol data container instance.""" 223 224 225
226 -def cartoon():
227 """Apply the PyMOL cartoon style and colour by secondary structure.""" 228 229 # Test if the current data pipe exists. 230 pipes.test() 231 232 # Test for the structure. 233 if not hasattr(cdp, 'structure'): 234 raise RelaxNoPdbError 235 236 # Loop over the PDB files. 237 open_files = [] 238 for model in cdp.structure.structural_data: 239 for mol in model.mol: 240 # Identifier. 241 pdb_file = mol.file_name 242 if mol.file_path: 243 pdb_file = mol.file_path + sep + pdb_file 244 id = file_root(pdb_file) 245 246 # Already loaded. 247 if pdb_file in open_files: 248 continue 249 250 # Add to the open file list. 251 open_files.append(pdb_file) 252 253 # Hide everything. 254 pymol_obj.exec_cmd("cmd.hide('everything'," + repr(id) + ")") 255 256 # Show the cartoon style. 257 pymol_obj.exec_cmd("cmd.show('cartoon'," + repr(id) + ")") 258 259 # Colour by secondary structure. 260 pymol_obj.exec_cmd("util.cbss(" + repr(id) + ", 'red', 'yellow', 'green')")
261 262
263 -def command(command):
264 """Function for sending PyMOL commands to the program pipe. 265 266 @param command: The command to send into the program. 267 @type command: str 268 """ 269 270 # Pass the command to PyMOL. 271 pymol_obj.exec_cmd(command)
272 273
274 -def cone_pdb(file=None):
275 """Display the cone geometric object. 276 277 @keyword file: The name of the file containing the cone geometric object. 278 @type file: str 279 """ 280 281 # Read in the cone PDB file. 282 pymol_obj.exec_cmd("load " + file) 283 284 285 # The cone axes. 286 ################ 287 288 # Select the AVE, AXE, and SIM residues. 289 pymol_obj.exec_cmd("select (resn AVE,AXE,SIM)") 290 291 # Show the vector as a stick. 292 pymol_obj.exec_cmd("show stick, 'sele'") 293 294 # Colour it blue. 295 pymol_obj.exec_cmd("color cyan, 'sele'") 296 297 # Select the atom used for labelling. 298 pymol_obj.exec_cmd("select (resn AVE,AXE,SIM and symbol N)") 299 300 # Hide the atom. 301 pymol_obj.exec_cmd("hide ('sele')") 302 303 # Label using the atom name. 304 pymol_obj.exec_cmd("cmd.label(\"sele\",\"name\")") 305 306 307 # The cone object. 308 ################## 309 310 # Select the CON residue. 311 pymol_obj.exec_cmd("select (resn CON,EDG)") 312 313 # Hide everything. 314 pymol_obj.exec_cmd("hide ('sele')") 315 316 # Show as 'sticks'. 317 pymol_obj.exec_cmd("show sticks, 'sele'") 318 319 # Colour it white. 320 pymol_obj.exec_cmd("color white, 'sele'") 321 322 # Shorten the stick width from 0.25 to 0.15. 323 pymol_obj.exec_cmd("set stick_radius,0.15000") 324 325 # Set a bit of transparency. 326 pymol_obj.exec_cmd("set stick_transparency, 0.3") 327 328 329 # Clean up. 330 ########### 331 332 # Remove the selection. 333 pymol_obj.exec_cmd("cmd.delete('sele')")
334 335
336 -def create_macro(data_type=None, style="classic", colour_start=None, colour_end=None, colour_list=None):
337 """Create an array of PyMOL commands. 338 339 @keyword data_type: The data type to map to the structure. 340 @type data_type: str 341 @keyword style: The style of the macro. 342 @type style: str 343 @keyword colour_start: The starting colour of the linear gradient. 344 @type colour_start: str or RBG colour array (len 3 with vals from 0 to 1) 345 @keyword colour_end: The ending colour of the linear gradient. 346 @type colour_end: str or RBG colour array (len 3 with vals from 0 to 1) 347 @keyword colour_list: The colour list to search for the colour names. Can be either 'molmol' or 'x11'. 348 @type colour_list: str or None 349 @return: The list of PyMOL commands. 350 @rtype: list of str 351 """ 352 353 # Get the specific macro. 354 api = return_api() 355 commands = api.pymol_macro(data_type, style, colour_start, colour_end, colour_list) 356 357 # Return the macro commands. 358 return commands
359 360
361 -def frame_order(ave_pos_file="ave_pos.pdb", rep_file="frame_order.pdb", dist_file="domain_distribution.pdb", dir=None):
362 """Display the frame order results (the geometric object, average position and distribution). 363 364 @keyword ave_pos_file: The name of the file for the average molecule structure. 365 @type ave_pos_file: str or None 366 @keyword rep_file: The name of the file of the PDB representation of the frame order dynamics to create. 367 @type rep_file: str or None 368 @keyword dist_file: The name of the file which will contain multiple models spanning the full dynamics distribution of the frame order model. 369 @type dist_file: str or None 370 @keyword dir: The name of the directory to place the PDB file into. 371 @type dir: str or None 372 """ 373 374 # The path. 375 path = '' 376 if dir != None: 377 path = dir + sep 378 379 # Set up the respective objects. 380 if ave_pos_file: 381 frame_order_ave_pos(file=path+ave_pos_file) 382 if rep_file: 383 frame_order_geometric(file=path+rep_file) 384 if dist_file: 385 frame_order_distribution(file=path+dist_file)
386 387
388 -def frame_order_ave_pos(file=None):
389 """Display the PDB structure for the frame order average domain position. 390 391 @keyword file: The name of the PDB file containing the frame order average structure. 392 @type file: str 393 """ 394 395 # Read in the PDB file. 396 pymol_obj.exec_cmd("load " + file) 397 398 # The object ID. 399 id = file_root(file)
400 401
402 -def frame_order_distribution(file=None):
403 """Display the PDB structure for the frame order distribution of domain positions. 404 405 @keyword file: The name of the PDB file containing the frame order distribution of domain positions. 406 @type file: str 407 """ 408 409 # Read in the PDB file. 410 pymol_obj.exec_cmd("load " + file)
411 412 413
414 -def frame_order_geometric(file=None):
415 """Display the frame order geometric object. 416 417 @keyword file: The name of the PDB file containing the frame order geometric object. 418 @type file: str 419 """ 420 421 # Read in the PDB file. 422 pymol_obj.exec_cmd("load " + file) 423 424 # The object ID. 425 id = file_root(file) 426 427 428 # Rotor objects. 429 ################ 430 431 # Set up the rotor axis (the residues AX and PRC). 432 pymol_obj.exec_cmd("select (resn AX,PRC)") 433 pymol_obj.exec_cmd("show stick, 'sele'") 434 pymol_obj.exec_cmd("color red, 'sele'") 435 pymol_obj.exec_cmd("cmd.delete('sele')") 436 437 # Display the central point. 438 pymol_obj.exec_cmd("select (name CTR)") 439 pymol_obj.exec_cmd("show spheres, 'sele'") 440 pymol_obj.exec_cmd("color red, 'sele'") 441 pymol_obj.exec_cmd("set sphere_scale, 0.3, 'sele'") 442 pymol_obj.exec_cmd("cmd.delete('sele')") 443 444 # Set up the propellers. 445 pymol_obj.exec_cmd("select (resn PRB)") 446 pymol_obj.exec_cmd("show stick, 'sele'") 447 pymol_obj.exec_cmd("set stick_radius, 0.15, 'sele'") 448 pymol_obj.exec_cmd("cmd.delete('sele')")
449 450 451 452
453 -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):
454 """Execute a PyMOL macro. 455 456 @keyword data_type: The data type to map to the structure. 457 @type data_type: str 458 @keyword style: The style of the macro. 459 @type style: str 460 @keyword colour_start_name: The name of the starting colour of the linear gradient. 461 @type colour_start_name: str 462 @keyword colour_start_rgb: The RGB array starting colour of the linear gradient. 463 @type colour_start_rgb: RBG colour array (len 3 with vals from 0 to 1) 464 @keyword colour_end_name: The name of the ending colour of the linear gradient. 465 @type colour_end_name: str 466 @keyword colour_end_rgb: The RGB array ending colour of the linear gradient. 467 @type colour_end_rgb: RBG colour array (len 3 with vals from 0 to 1) 468 @keyword colour_list: The colour list to search for the colour names. Can be either 'molmol' or 'x11'. 469 @type colour_list: str or None 470 """ 471 472 # Test if the current data pipe exists. 473 pipes.test() 474 475 # Test if sequence data exists. 476 if not exists_mol_res_spin_data(): 477 raise RelaxNoSequenceError 478 479 # Check the arguments. 480 if colour_start_name != None and colour_start_rgb != None: 481 raise RelaxError("The starting colour name and RGB colour array cannot both be supplied.") 482 if colour_end_name != None and colour_end_rgb != None: 483 raise RelaxError("The ending colour name and RGB colour array cannot both be supplied.") 484 485 # Merge the colour args. 486 if colour_start_name != None: 487 colour_start = colour_start_name 488 else: 489 colour_start = colour_start_rgb 490 if colour_end_name != None: 491 colour_end = colour_end_name 492 else: 493 colour_end = colour_end_rgb 494 495 # Clear the PyMOL history first. 496 pymol_obj.clear_history() 497 498 # Create the macro. 499 commands = create_macro(data_type=data_type, style=style, colour_start=colour_start, colour_end=colour_end, colour_list=colour_list) 500 501 # Save the commands as a temporary file, execute it, then delete it. 502 try: 503 # Temp file name. 504 tmpfile = "%s.pml" % mktemp() 505 506 # Open the file. 507 file = open(tmpfile, 'w') 508 509 # Loop over the commands and write them. 510 for command in commands: 511 file.write("%s\n" % command) 512 file.close() 513 514 # Execute the macro. 515 pymol_obj.exec_cmd("@%s" % tmpfile) 516 517 # Wait a bit for PyMOL to catch up (it takes time for PyMOL to start and the macro to execute). 518 sleep(3) 519 520 # Delete the temporary file (no matter what). 521 finally: 522 # Delete the file. 523 delete(tmpfile, fail=False)
524 525
526 -def macro_run(file=None, dir=None):
527 """Execute the PyMOL macro from the given text file. 528 529 @keyword file: The name of the macro file to execute. 530 @type file: str 531 @keyword dir: The name of the directory where the macro file is located. 532 @type dir: str 533 """ 534 535 # Open the file for reading. 536 file_path = get_file_path(file, dir) 537 file = open_read_file(file, dir) 538 539 # Loop over the commands and apply them. 540 for command in file.readlines(): 541 pymol_obj.exec_cmd(command)
542 543
544 -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):
545 """Create a PyMOL macro file. 546 547 @keyword data_type: The data type to map to the structure. 548 @type data_type: str 549 @keyword style: The style of the macro. 550 @type style: str 551 @keyword colour_start_name: The name of the starting colour of the linear gradient. 552 @type colour_start_name: str 553 @keyword colour_start_rgb: The RGB array starting colour of the linear gradient. 554 @type colour_start_rgb: RBG colour array (len 3 with vals from 0 to 1) 555 @keyword colour_end_name: The name of the ending colour of the linear gradient. 556 @type colour_end_name: str 557 @keyword colour_end_rgb: The RGB array ending colour of the linear gradient. 558 @type colour_end_rgb: RBG colour array (len 3 with vals from 0 to 1) 559 @keyword colour_list: The colour list to search for the colour names. Can be either 'molmol' or 'x11'. 560 @type colour_list: str or None 561 @keyword file: The name of the macro file to create. 562 @type file: str 563 @keyword dir: The name of the directory to place the macro file into. 564 @type dir: str 565 @keyword force: Flag which if set to True will cause any pre-existing file to be overwritten. 566 @type force: bool 567 """ 568 569 # Test if the current data pipe exists. 570 pipes.test() 571 572 # Test if sequence data exists. 573 if not exists_mol_res_spin_data(): 574 raise RelaxNoSequenceError 575 576 # Check the arguments. 577 if colour_start_name != None and colour_start_rgb != None: 578 raise RelaxError("The starting colour name and RGB colour array cannot both be supplied.") 579 if colour_end_name != None and colour_end_rgb != None: 580 raise RelaxError("The ending colour name and RGB colour array cannot both be supplied.") 581 582 # Merge the colour args. 583 if colour_start_name != None: 584 colour_start = colour_start_name 585 else: 586 colour_start = colour_start_rgb 587 if colour_end_name != None: 588 colour_end = colour_end_name 589 else: 590 colour_end = colour_end_rgb 591 592 # Create the macro. 593 commands = create_macro(data_type=data_type, style=style, colour_start=colour_start, colour_end=colour_end, colour_list=colour_list) 594 595 # File name. 596 if file == None: 597 file = data_type + '.pml' 598 599 # Open the file for writing. 600 file_path = get_file_path(file, dir) 601 file = open_write_file(file, dir, force) 602 603 # Loop over the commands and write them. 604 for command in commands: 605 file.write(command + "\n") 606 607 # Close the file. 608 file.close() 609 610 # Add the file to the results file list. 611 add_result_file(type='pymol', label='PyMOL', file=file_path)
612 613
614 -def tensor_pdb(file=None):
615 """Display the diffusion tensor geometric structure. 616 617 @keyword file: The name of the file containing the diffusion tensor geometric object. 618 @type file: str 619 """ 620 621 # Test if the current data pipe exists. 622 pipes.test() 623 624 # Read in the tensor PDB file. 625 pymol_obj.exec_cmd("load " + file) 626 627 628 # The tensor object. 629 #################### 630 631 # Select the TNS residue. 632 pymol_obj.exec_cmd("select resn TNS") 633 634 # Hide everything. 635 pymol_obj.exec_cmd("hide ('sele')") 636 637 # Show as 'sticks'. 638 pymol_obj.exec_cmd("show sticks, 'sele'") 639 640 641 # Centre of mass. 642 ################# 643 644 # Select the COM residue. 645 pymol_obj.exec_cmd("select resn COM") 646 647 # Show the centre of mass as the dots representation. 648 pymol_obj.exec_cmd("show dots, 'sele'") 649 650 # Colour it blue. 651 pymol_obj.exec_cmd("color blue, 'sele'") 652 653 654 # The diffusion tensor axes. 655 ############################ 656 657 # Select the AXS residue. 658 pymol_obj.exec_cmd("select resn AXS") 659 660 # Hide everything. 661 pymol_obj.exec_cmd("hide ('sele')") 662 663 # Show as 'sticks'. 664 pymol_obj.exec_cmd("show sticks, 'sele'") 665 666 # Colour it cyan. 667 pymol_obj.exec_cmd("color cyan, 'sele'") 668 669 # Select the N atoms of the AXS residue (used to display the axis labels). 670 pymol_obj.exec_cmd("select (resn AXS and elem N)") 671 672 # Label the atoms. 673 pymol_obj.exec_cmd("label 'sele', name") 674 675 676 677 # Monte Carlo simulations. 678 ########################## 679 680 # Select the SIM residue. 681 pymol_obj.exec_cmd("select resn SIM") 682 683 # Colour it. 684 pymol_obj.exec_cmd("colour cyan, 'sele'") 685 686 687 # Clean up. 688 ########### 689 690 # Remove the selection. 691 pymol_obj.exec_cmd("cmd.delete('sele')")
692 693
694 -def vector_dist(file=None):
695 """Display the XH bond vector distribution. 696 697 @keyword file: The vector distribution PDB file. 698 @type file: str 699 """ 700 701 # Test if the current data pipe exists. 702 pipes.test() 703 704 # The file root. 705 id = file_root(file) 706 707 # Read in the vector distribution PDB file. 708 pymol_obj.exec_cmd("load " + file) 709 710 711 # Create a surface. 712 ################### 713 714 # Select the vector distribution. 715 pymol_obj.exec_cmd("cmd.show('surface', " + repr(id) + ")")
716 717
718 -def view():
719 """Start PyMOL.""" 720 721 # Open PyMOL. 722 if pymol_obj.running(): 723 raise RelaxError("PyMOL is already running.") 724 else: 725 pymol_obj.open_gui()
726