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