#!/usr/bin/env ccp4-python # # Copyright (C) 2014 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. # # Class for running SHELXE for c-alpha tracing # # Ronan Keegan 21/11/2014 import sys, os, string import shlex, subprocess import shutil # Update the python path with the mrbump folders if not "CCP4" in sorted(os.environ.keys()): raise RuntimeError('CCP4 not found') if os.path.isdir(os.path.join(os.environ["CCP4"], "share", "mrbump")): sys.path.append(os.path.join(os.environ["CCP4"], "share", "mrbump", "include", "file_info")) sys.path.append(os.path.join(os.environ["CCP4"], "share", "mrbump", "include", "tools")) else: sys.stdout.write("Error: Can't find MrBUMP folders\n\n") sys.exit() import MTZ_parse import MRBUMP_phs2mtz def which(program): def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None # Test for required executables if os.name == "nt": if not which("mtz2various.exe"): raise RuntimeError('mtz2various.exe not found') else: if not which("mtz2various"): raise RuntimeError('mtz2various not found') #if not which("shelxe"): # raise RuntimeError('shelxe not found') class Shelxe: def __init__(self): self.pdbinFile="" self.mtzinFile="" self.hklinFile="" self.pdboutFile="" self.mtzoutFile="" self.phsoutFile="" self.shelxScriptFile="shelx-script.sh" self.script="" self.labin=dict([]) self.debug=True self.mtz2variousLogfile="mtz2various.log" self.shelxeLogfile="shelxe.log" self.workingDIR="" def setDebug(self, debugValue): self.debug=debugValue def setShelxScriptFile(self, filename): self.shelxScriptFile=filename def setShelxeLogFile(self, filename): self.shelxeLogfile=filename def setShelxWorkingDIR(self, dirname): self.workingDIR=dirname def checkFileExist(self, filename, program, type): """ Check to see if the PDB file has been outout from Refmac in MrBUMP """ if os.path.isfile(filename): status = 0 else: status = 1 sys.stdout.write("Warning: no file output from "+ program +" for this job\n") return status def runMtz2Various(self, fp="FP", sigfp="SIGFP", free="FreeR_flag"): """ Run mtz2various to convert the MTZ file for Shelxe """ self.hklinFile=os.path.splitext(os.path.split(self.mtzinFile)[-1])[0] + ".hkl" command_line='mtz2various HKLIN %s HKLOUT %s' % (self.mtzinFile, self.hklinFile) self.script += command_line + " << eof\n" key = "LABIN FP=%s SIGFP=%s FREE=%s\n" % (fp, sigfp, free) key += "OUTPUT SHELX\n" key += "FSQUARED\n" key += "END\n" self.script += key + "eof\n\n" if os.name == "nt": process_args = shlex.split(command_line, posix=False) p = subprocess.Popen(process_args, bufsize=0, shell="False", 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) #process_args = shlex.split(command_line) #p = subprocess.Popen(process_args, stdin = subprocess.PIPE, # stdout = subprocess.PIPE, stderr=subprocess.STDOUT) (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) # Write the keyword input child_stdin.write(key) child_stdin.close() # Watch the output for successful termination out=child_stdout_and_stderr.readline() log=open(self.mtz2variousLogfile, "w") while out: out=child_stdout_and_stderr.readline() log.write(out) if self.debug: sys.stdout.write(out) child_stdout_and_stderr.close() log.close() status=self.checkFileExist(self.hklinFile, "mtz2various", "hkl") if status==1: sys.stdout.write("Error: No output file from mtz2various\n") def runMtz2hkl(self, rfree_flag=""): """ Run mtz2hkl to convert the MTZ file for Shelx """ if rfree_flag != "": command_line='mtz2hkl -2 orig -r %s' % rfree_flag else: command_line='mtz2hkl -2 orig' self.script += command_line + "\n" if os.name == "nt": process_args = shlex.split(command_line, posix=False) p = subprocess.Popen(process_args, bufsize=0, shell="False", 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) # process_args = shlex.split(command_line) # p = subprocess.Popen(process_args, stdin = subprocess.PIPE, # stdout = subprocess.PIPE, stderr=subprocess.STDOUT) (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) # Write the keyword input child_stdin.close() # Watch the output for successful termination out=child_stdout_and_stderr.readline() while out: sys.stdout.write(out) out=child_stdout_and_stderr.readline() child_stdout_and_stderr.close() status=self.checkFileExist("orig.hkl", "mtz2hkl", "hkl") if status==1: sys.stdout.write("Error: No output file from mtz2hkl\n") def runShelxe(self, solvent, pdbinFile, mtzinFile, workingDIR, pdboutFile="shelxe-output.pdb", \ mtzoutFile="shelxe-output.mtz", phsoutFile="shelxe-output.phs", traceCycles=15, \ dmCycles=20, shelxeEXE="shelxe", WEB_PATH_START=0): """ Run shelxe """ # Give a header output sys.stdout.write("############################################################\n") sys.stdout.write("Running Shelxe to do phase improvement and c-alpha trace...\n") sys.stdout.write("############################################################\n") sys.stdout.write("\n") self.workingDIR=workingDIR if os.path.isdir(self.workingDIR) == False: try: os.mkdir(self.workingDIR) except: sys.stderr.write("Error: Can't create working directory:\n %s\n" % self.workingDIR) sys.exit() sys.stdout.write("Running directory is:\n %s \n" % self.workingDIR) sys.stdout.write("\n") self.mtzinFile=mtzinFile self.pdbinFile=pdbinFile self.pdboutFile=pdboutFile self.mtzoutFile=mtzoutFile self.phsoutFile=phsoutFile currDIR=os.getcwd() os.chdir(self.workingDIR) mtz = MTZ_parse.MTZ_parse() mtz.run_mtzdmp(self.mtzinFile) self.runMtz2Various(mtz.F, mtz.SIGF, mtz.FreeR_flag) if mtz.resolution<=2.0: free_lunch=" -e1.0 -l5" else: free_lunch="" if solvent > 1.0: frac_solvent=solvent/100.0 else: frac_solvent=solvent command_line_args=' -a' + str(traceCycles) + ' -m' + str(dmCycles) + \ ' -q -s' + str(frac_solvent) + ' -o -n -t4' + free_lunch # Set up input files for shelxe if os.path.isfile("shelxe-input.hkl"): os.remove("shelxe-input.hkl") shutil.copyfile(self.hklinFile, "shelxe-input.hkl") self.script += "cp %s shelxe-input.hkl\n" % self.hklinFile if os.path.isfile("shelxe-input.pda"): os.remove("shelxe-input.pda") shutil.copyfile(self.pdbinFile, "shelxe-input.pda") self.script += "cp %s shelxe-input.pda\n\n" % self.pdbinFile command_line=shelxeEXE + ' shelxe-input.pda' + command_line_args self.script += command_line + "\n\n" file=open(self.shelxScriptFile, "w") file.write(self.script) file.close() if os.name == "nt": process_args = shlex.split(command_line, posix=False) p = subprocess.Popen(process_args, bufsize=0, shell="False", 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_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) # Write the keyword input child_stdin.close() # Watch the output for successful termination out=child_stdout_and_stderr.readline() cycle=1 CAPTURE=False #capture_count=0 #frag_count=0 #GET_FRAGS=True #acl=0.0 log=open(self.shelxeLogfile, "w") while out: log.write(out) if "residues left after pruning" in out and "divided into chains" in out: CAPTURE=True sys.stdout.write("---------------------------------\n") sys.stdout.write("SHELXE tracing cycle: %d\n" % cycle) sys.stdout.write("---------------------------------\n") sys.stdout.write("\n") cycle=cycle+1 if self.debug == False and CAPTURE: sys.stdout.write(" " + string.strip(out) + "\n") #if CAPTURE and capture_count >= 1 and string.strip(out) != "" and GET_FRAGS: # for i in string.split(out): # if ":" not in i: # frag_count=frag_count+1 # acl=(acl+float(i))/float(frag_count) #if CAPTURE and acl > 0.0 and string.strip(out) == "": # GET_FRAGS=False if "CC for partial structure against native data" in out: CAPTURE=False # frag_count=0 # acl=0 # capture_count=0 sys.stdout.write("\n") if self.debug==False and "Best trace (cycle " in out: sys.stdout.write(" " + string.split(string.strip(out),"was")[0] + "\n") sys.stdout.write("\n") if self.debug: sys.stdout.write(out) #if CAPTURE: # capture_count=capture_count+1 out=child_stdout_and_stderr.readline() child_stdout_and_stderr.close() log.close() pdbstatus=self.checkFileExist("shelxe-input.pdb", "shelxe", "pdb") if pdbstatus==1: sys.stdout.write("Error: No output pdb file from shelxe\n") script = "# No output from SHELXE\n" else: shutil.move("shelxe-input.pdb", self.pdboutFile) script = "mv shelxe-input.pdb %s\n" % self.pdboutFile phsstatus=self.checkFileExist("shelxe-input.phs", "shelxe", "phs") if phsstatus==1: sys.stdout.write("Error: No output phs file from shelxe\n") else: shutil.move("shelxe-input.phs", self.phsoutFile) script += "mv shelxe-input.phs %s\n\n" % self.phsoutFile c=MRBUMP_phs2mtz.PHS2MTZ() if mtz.FreeR_flag != "": c.phs2mtz(self.phsoutFile, self.pdboutFile, self.mtzoutFile, os.getcwd(), hklref=self.mtzinFile, freeLabel=mtz.FreeR_flag, resolution=mtz.resolution, debug=self.debug) else: c.phs2mtz(self.phsoutFile, self.pdboutFile, self.mtzoutFile, os.getcwd(), resolution=mtz.resolution, debug=self.debug) scriptFile=open(self.shelxScriptFile, "a") scriptFile.write(script) scriptFile.close() # Set the best scores if os.path.isfile(self.pdboutFile): score=0.0 acl=0.0 f=open(self.pdboutFile, "r") line=f.readline() try: score=float(string.split(line)[6].replace("%","")) acl=float(string.split(line)[7])/float(string.split(line)[10]) except: sys.stdout.write("Warning (shelxe_trace): Can't find Shelxe output score in output pdb\n") f.close() sys.stdout.write("Log file written to:\n %s \n" % self.shelxeLogfile[WEB_PATH_START:]) sys.stdout.write("\n") if pdbstatus != 1: sys.stdout.write("Output PDB file written to:\n %s \n" % self.pdboutFile[WEB_PATH_START:]) sys.stdout.write("\n") if self.debug == False: for file in self.hklinFile, "shelxe-input.hkl", "shelxe-input.pdb", \ "shelxe-input.pha", "shelxe-input.hat", \ "shelxe-input.pda": if os.path.isfile(file): os.remove(file) os.chdir(currDIR) if __name__ == "__main__": if len(sys.argv) == 7: pdbinFile=sys.argv[1] mtzinFile=sys.argv[2] solvent=float(sys.argv[3]) workingDIR=sys.argv[4] pdboutFile=sys.argv[5] mtzoutFile=sys.argv[6] elif len(sys.argv) == 9: pdbinFile=sys.argv[1] mtzinFile=sys.argv[2] solvent=float(sys.argv[3]) workingDIR=sys.argv[4] pdboutFile=sys.argv[5] mtzoutFile=sys.argv[6] traceCycles=sys.argv[7] dmCycles=sys.argv[8] else: sys.stdout.write("Usage: ccp4-python shelxe4mr.py [optional: ]\n") sys.stdout.write("\n") sys.stdout.write(" e.g. ccp4-python shelxe4mr.py foo.pdb foo.mtz 45.33 /tmp/test bar.pdb bar.mtz 15 20\n") sys.stdout.write("\n") sys.exit() SHELX=Shelxe() status=SHELX.checkFileExist(pdbinFile, "mrbump", "pdb") if status==1: sys.exit(1) status=SHELX.checkFileExist(mtzinFile, "mtzfile", "mtz") if status==1: sys.exit(1) SHELX.runShelxe(solvent, pdbinFile, mtzinFile, workingDIR, pdboutFile=pdboutFile, mtzoutFile=mtzoutFile, traceCycles=traceCycles, dmCycles=dmCycles)