#! /usr/bin/env ccp4-python # # Copyright (C) 2005 Ronan Keegan # # This code is distributed under the terms and conditions of the # CCP4 Program Suite Licence Agreement as a CCP4 Application. # A copy of the CCP4 licence can be obtained by writing to the # CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK. # # A MrBUMP wrapper for Phaser # Ronan Keegan - 29/1/07 # import os, sys import string import time import signal import subprocess import shlex if not os.environ.has_key('CCP4'): raise RuntimeError, 'CCP4 not found' if not os.environ.has_key('CBIN'): raise RuntimeError, 'CBIN not found' class PhaserEXE: """ A class to run a Phaser job. """ def __init__(self): if os.name=="nt": self.phaserEXE = os.path.join(os.environ["CBIN"], "phaser.exe") self.mtzdumpEXE = os.path.join(os.environ["CBIN"], "mtzdump.exe") else: self.phaserEXE = os.path.join(os.environ["CBIN"], "phaser") self.mtzdumpEXE = os.path.join(os.environ["CBIN"], "mtzdump") self.logfile = "" self.hklout = "" self.pdbout = "" self.key = "" self.keywords = [] self.termination=False self.soln_spacegroup="" self.soln_found=False try: self.debug=eval(os.environ['MRBUMP_DEBUG']) except: self.debug=False self.local_debug = False def set_logfile(self, filename): self.logfile=filename def set_hklout(self, filename): self.hklout=filename def set_pdbout(self, filename): self.pdbout=filename def add_keyword(self, keyword): self.keywords.append(keyword) def check_SG(self, mtzfile): """ Check the spacegroup of the Phaser solution from the output MTZ file. hklout - output mtz file from Phaser, hklinSG - the spacegroup of the input MTZ file""" # Run mtzdump to dump the file details # Check the file exists if os.path.isfile(mtzfile): # Set the command line command_line=self.mtzdumpEXE + " HKLIN " + mtzfile # Launch mtzdump if os.name == "nt": process_args = shlex.split(command_line, posix=False) p = subprocess.Popen(process_args, shell="True", stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) else: process_args = shlex.split(command_line) p = subprocess.Popen(process_args, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) (child_stdout, child_stdin) = (p.stdout, p.stdin) # Write the keyword input child_stdin.write("GO\n") child_stdin.close() # Watch the output for successful termination out=child_stdout.readline() while out: if self.local_debug: sys.stdout.write(out) if 'Space group' in out: self.soln_spacegroup=string.split(out,"'")[1] out=child_stdout.readline() child_stdout.close() else: # Report an error sys.stdout.write("Phaser output MTZ error: file not found\n") sys.stdout.write("\n") def run(self, working_DIR, hklout, pdbout, logfile, script="", keyfile="", LITE=False, KILLPHASER=False, KILLTIME=600.0, WEB_PATH_START=0): """ Function to launch a phaser job. LITE = boolean to control removal of files for light running of MrBUMP """ # Change to the Phaser working directory curr_DIR=os.getcwd() os.chdir(working_DIR) # Give a header output sys.stdout.write("#######################################\n") sys.stdout.write("Running Phaser...... \n") sys.stdout.write("#######################################\n") sys.stdout.write("\n") # Check to see if the logfile has been specified, otherwise give it a default name if self.logfile=="": self.logfile=logfile # Set HKLOUT if it has not been set already if self.hklout=="": self.hklout=hklout # Set PDBOUT if self.pdbout=="": self.pdbout=pdbout # Set the keywords for the job if keyfile == "": # If no keyword file is given read keywords from the input keywords for keyword in self.keywords: #self.key=self.key + keyword self.key=self.key + keyword + "\n" else: # Read keywords from the keyword file kfile=open(keyfile, "r") line=kfile.readline() while line: self.key = self.key + line line=kfile.readline() kfile.close() # Output the keywords if in debug mode if self.local_debug: sys.stdout.write("#########################\n") sys.stdout.write("Phaser keyword input:\n") sys.stdout.write("#########################\n") sys.stdout.write("\n") sys.stdout.write(self.key) sys.stdout.write("\n") time.sleep(2) # Set the command line command_line=self.phaserEXE # if in Debug mode write out the run script for this Phaser job if (self.debug or LITE) and os.name != "nt" and script!="": try: line = "#! /bin/sh\n\n" line+= "%s << eof\n" % command_line line+= "%s" % self.key line+= "eof\n" f=open(script, "w") f.write(line) f.close() os.chmod(script,0755) except: sys.stdout.write("Script write warning: Could not write phaser run script\n") sys.stdout.write("\n") start=time.time() # Launch Phaser if os.name == "nt": process_args = shlex.split(command_line, posix=False) p = subprocess.Popen(process_args, shell="True", stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) else: process_args = shlex.split(command_line) p = subprocess.Popen(process_args, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, preexec_fn=os.setsid) (child_stdout, child_stdin) = (p.stdout, p.stdin) # Write the keyword input child_stdin.write(self.key) child_stdin.close() log=open(self.logfile, "w") # Watch the output for successful termination out=child_stdout.readline() log.write(out) if self.debug: sys.stdout.write(out) while out: if self.local_debug: sys.stdout.write(out) if 'EXIT STATUS: FAILURE' in out: self.termination=False out=child_stdout.readline() log.write(out) # If we want to stop Phaser after a certain length of time: if os.name != "nt" and KILLPHASER: elapsed=(time.time()-start) if elapsed >= KILLTIME: os.killpg(p.pid, signal.SIGTERM) os.killpg(p.pid, signal.SIGKILL) break child_stdout.close() log.close() # Check the output # Check for the output files: if os.path.exists(self.pdbout): self.termination = True else: self.termination = False # If this is an anisotropic correction run of phaser only an MTZ is produced. if "MODE MR_ANO" in self.key: if os.path.exists(self.hklout): self.termination = True else: self.termination = False # Report the result if self.termination == False: self.soln_found=False sys.stdout.write("Phaser Error: phaser failed to complete successfully\n") if LITE: sys.stdout.write("Running in 'LITE' mode. Phaser job can be re-run using:\n %s\n" % script) else: sys.stdout.write("Log file can be found here:\n") sys.stdout.write(" " + self.logfile[WEB_PATH_START:] + "\n") sys.stdout.write("\n") else: self.soln_found=True sys.stdout.write("Phaser completed successfully\n") if LITE: sys.stdout.write("Running in 'LITE' mode. Output files from Phaser have been removed but can be re-generated by running:\n %s\n" % script) else: sys.stdout.write("Output Log file written to:\n " + self.logfile[WEB_PATH_START:] + "\n") sys.stdout.write("Output MTZ file written to:\n " + self.hklout[WEB_PATH_START:] + "\n") if "MODE MR_ANO" not in self.key: sys.stdout.write("Output PDB file written to:\n " + self.pdbout[WEB_PATH_START:] + "\n") sys.stdout.write("\n") # Revert to working directory os.chdir(curr_DIR)