def convert_intensities_to_amplitudes(mtzin, mtzout): """Takes an input mtz and converts the intensities to structure factors for model building""" mtzobj = MtzSummary(mtzin) # Copy data columns from new mtz file I, SIGI = mtzobj.label.i, mtzobj.label.sigi if not (I and SIGI): raise LabelError('No Intensities found in {!s}'.format(mtzin)) # TODO If rfree is present, retain rfree from the reference mtz # RFree = mtzobj.label.free # Initialise Commander CTRUNC = CommandManager('ctruncate') # Set command arguments CTRUNC.add_command_line_arguments('-mtzin', mtzin, '-mtzout', mtzout, '-colin', '/*/*/[{!s},{!s}]'.format(I, SIGI)) # Run! CTRUNC.run() if not os.path.exists(mtzout): raise ExternalProgramError( 'CTRUNCATE has failed to convert intensities to SFs. {!s}\nOUT: {!s}\nERR: {!s}' .format(mtzin, CTRUNC.out, CTRUNC.err)) return CTRUNC
def generate_symmetry_mates(pdbin, pdbout, sgno, cell): """Takes the input pdb and generates the unit cell from the point group symmetry""" if not pdbout.endswith('.pdb'): pdbout = pdbout + '.pdb' if not os.path.exists(pdbin): raise IOError('pdbin does not exist! {!s}'.format(pdbin)) if os.path.exists(pdbout): raise Exception('pdbout already exists! {!s}'.format(pdbout)) assert isinstance(sgno, int), 'SPACEGROUP MUST BE AN INTEGER! {!s}'.format(sgno) assert isinstance(cell, list), 'CELL MUST BE A LIST! {!s}'.format(cell) # Initialise Commander PDBSET = CommandManager('pdbset') # Set Command Arguments PDBSET.add_command_line_arguments('XYZIN', os.path.abspath(pdbin), 'XYZOUT', os.path.abspath(pdbout)) # Set inputs PDBSET.add_standard_input([ 'SYMGEN {!s}'.format(sgno), 'CELL {!s}'.format(' '.join(map(str, cell))), 'END' ]) # run! PDBSET.run() if not os.path.exists(pdbout): raise ExternalProgramError( 'PDBSET has failed to generate SYMMETRY mates. {!s}\nCOM: {!s}\nOUT: {!s}\nERR: {!s}' .format(pdbin, PDBSET.command, PDBSET.out, PDBSET.err)) return pdbout
def generate_ligand_with_acedrg(smiles, name='LIG', prefix='ligand', verbose=False): """Generate pdb and cif files from smiles string""" assert len(name) == 3 smiles = smiles.replace('CL', 'Cl') smiles = smiles.replace('BR', 'Br') out_pdb = prefix + '.pdb' out_cif = prefix + '.cif' if os.path.exists(out_pdb): raise Exception('Output PDB file already exists') if os.path.exists(out_cif): raise Exception('Output CIF file already exists') # Run acedrg acedrg = CommandManager('acedrg') acedrg.add_command_line_arguments(['--smi={}'.format(smiles)]) acedrg.add_command_line_arguments(['-r', name]) acedrg.add_command_line_arguments(['-o', prefix]) if verbose: acedrg.print_settings() acedrg.run() if not (os.path.exists(out_pdb) and os.path.exists(out_cif)): e = Exception('acedrg failed during ligand generation') e.command = acedrg raise e return out_pdb, out_cif
def map_to_reference_using_symmetry(refpdb, movpdb, pdbout, conrad=5): """Transforms `movpdb` to the closest symmetry site to `refpdb` using csymmatch - Symmetry info must be contained in the header of the pdb file""" if not pdbout.endswith('.pdb'): pdbout = pdbout + '.pdb' if not os.path.exists(refpdb): raise IOError('refpdb does not exist! {!s}'.format(refpdb)) if not os.path.exists(movpdb): raise IOError('movpdb does not exist! {!s}'.format(movpdb)) if os.path.exists(pdbout): raise Exception('pdbout already exists! {!s}'.format(pdbout)) # Initialise Commander CSYMMATCH = CommandManager('csymmatch') # Set Command Arguments CSYMMATCH.add_command_line_arguments('-pdbin-ref', os.path.abspath(refpdb), '-pdbin', os.path.abspath(movpdb), '-pdbout', os.path.abspath(pdbout), '-connectivity-radius', str(conrad)) # run! CSYMMATCH.run() if not os.path.exists(pdbout): raise ExternalProgramError( 'CSYMMATCH has failed to map {!s} to {!s}.\nERR: {!s}'.format( movpdb, refpdb, CSYMMATCH.err)) return pdbout
def create_alpha_carbon_backbone(pdbin, pdbout): """Takes a pdb files and removes eveything except for the alpha carbons""" if not pdbout.endswith('.pdb'): pdbout = pdbout + '.pdb' if not os.path.exists(pdbin): raise IOError('pdbin does not exist! {!s}'.format(pdbin)) if os.path.exists(pdbout): raise Exception('pdbout already exists! {!s}'.format(pdbout)) # Initialise Commander PDBCUR = CommandManager('pdbcur') # Set Command Arguments PDBCUR.add_command_line_arguments('XYZIN', pdbin, 'XYZOUT', pdbout) # Set inputs PDBCUR.add_standard_input(['lvatom "CA[C]:*"', 'END']) # run! PDBCUR.run() if not os.path.exists(pdbout): raise ExternalProgramError( 'PDBCUR has failed to create carbon backbone. {!s}\nOUT: {!s}\nERR: {!s}' .format(pdbin, PDBCUR.out, PDBCUR.err)) return pdbout
def create_cryst_line(pdbin, pdbout, sg, cell): """Adds a cryst line to pdbin""" if not pdbout.endswith('.pdb'): pdbout = pdbout + '.pdb' if not os.path.exists(pdbin): raise IOError('pdbin does not exist! {!s}'.format(pdbin)) if os.path.exists(pdbout): raise Exception('pdbout already exists! {!s}'.format(pdbout)) # Initialise Commander PDBSET = CommandManager('pdbset') # Set Command Arguments PDBSET.add_command_line_arguments('XYZIN', os.path.abspath(pdbin), 'XYZOUT', os.path.abspath(pdbout)) # Set Stdin PDBSET.add_standard_input([ 'SPACEGROUP {!s}'.format(sg), 'CELL {!s}'.format(' '.join(map(str, cell))) ]) # run! PDBSET.run() if not os.path.exists(pdbout): raise ExternalProgramError( 'PDBSET has failed to create cryst line for {!s}\nOUT: {!s}\nERR: {!s}' .format(pdbin, PDBSET.out, PDBSET.err)) return PDBSET
def extract_bfactor_statistics(pdb_file): """Analyse the b-factors in a pdb file and return a dictionary with all of the averages, rms deviations and Z-scores for the b-factors in a structure""" # Create a temporary file for the output summary table and pdb_file temp_handle, temp_path = tempfile.mkstemp(suffix='.table', prefix='baverage_') temp_handle2, temp_path2 = tempfile.mkstemp(suffix='.pdb', prefix='baverage_') BAVERAGE = CommandManager('baverage') BAVERAGE.add_command_line_arguments('XYZIN', pdb_file, 'RMSTAB', temp_path, 'XYZOUT', temp_path2) BAVERAGE.add_standard_input(['END']) BAVERAGE.run() if not os.path.exists(temp_path): raise ExternalProgramError( 'BAVERAGE has failed to calculate b-factor summary statistics for {!s}' .format(pdb_file)) # Process Table and Standard Out table_contents = open(temp_path, 'r').read().split('\n') if not table_contents: raise ExternalProgramError( 'BAVERAGE has failed to calculate b-factor summary statistics for {!s}' .format(pdb_file)) else: os.remove(temp_path) os.remove(temp_path2) return BAVERAGE, table_contents
def apply_rfree_set(refmtz, mtzin, mtzout): """Takes an input mtz and a reference mtz and transplants the rfree flags""" tempmtz = mtzin.replace('.mtz', '.temp.mtz') refobj = MtzSummary(refmtz) newobj = MtzSummary(mtzin) # Copy data columns from new mtz file F1, SIGF1 = newobj.label.f, newobj.label.sigf if not (F1 and SIGF1): raise LabelError('No Amplitudes found in {!s}'.format(mtzin)) # Get the spacegroup and the rfree from the reference mtz sgno = refobj.data.spacegroupno RFree2 = refobj.label.free if not sgno: raise LabelError( 'No Spacegroup information found in {!s}'.format(refmtz)) if not RFree2: raise LabelError('No RFreeFlags found in {!s}'.format(refmtz)) # Initialise Commander CAD = CommandManager('cad') # Set command arguments CAD.add_command_line_arguments('hklin1', mtzin, 'hklin2', refmtz, 'hklout', tempmtz) # Set inputs CAD.add_standard_input(['symmetry {!s}'.format(sgno),'labin file_number 1 E1={!s} E2={!s}'.format(F1, SIGF1), \ 'labout file_number 1 E1={!s} E2={!s}'.format(F1, SIGF1), \ 'labin file_number 2 E1={!s}'.format(RFree2), \ 'labout file_number 2 E1={!s}'.format(RFree2),'END']) # Run! CAD.run() if not os.path.exists(tempmtz): raise ExternalProgramError( 'CAD has failed to transplant RFree Flags. {!s}\nOUT: {!s}\nERR: {!s}' .format(mtzin, CAD.out, CAD.err)) # Now complete the free r set # Initialise Commander FREE = CommandManager('freerflag') # Set command arguments FREE.add_command_line_arguments('hklin', tempmtz, 'hklout', mtzout) # Set inputs FREE.add_standard_input(['COMPLETE FREE={!s}'.format(RFree2), 'END']) # Run! FREE.run() if not os.path.exists(mtzout): raise ExternalProgramError( 'freerflag has failed to complete the RFree Flag set. {!s}\nOUT: {!s}\nERR: {s}' .format(tempmtz, CAD.out, CAD.err)) os.remove(tempmtz) return CAD, FREE
def isolate_residue(inpdb, outpdb, resname): """Extract the residues identified by resname using pdbcur - i.e. 'UNL'""" PDBCUR = CommandManager('pdbcur') PDBCUR.add_command_line_arguments('XYZIN', inpdb, 'XYZOUT', outpdb) PDBCUR.add_standard_input(['lvresidue /*/*/({!s})'.format(resname), 'END']) PDBCUR.run() return PDBCUR
def run(cls, script): assert script.endswith(cls._file_type) c = CommandManager('pymol') c.add_command_line_arguments([ '-k', '-q', '-c', '-Q', '-s', script[:-len(cls._file_type)] + '.log', '-r', script ]) c.run() return c
def merge_pdb_files(pdb1, pdb2, pdbout): """Merge two PDB Files using CCP4s pdb_merge""" # Initialise Commander MERGER = CommandManager('pdb_merge') # Set command arguments MERGER.add_command_line_arguments('xyzin1', pdb1, 'xyzin2', pdb2, 'xyzout', pdbout) # Set inputs MERGER.add_standard_input('END') # run! MERGER.run() return MERGER
def run(params): assert params.input.mtz, 'No MTZs given for comparison' assert not os.path.exists( params.output.merged_mtz ), 'The output file ({}) already exists. Please delete it before re-running.'.format( params.output.merged_mtz) assert not os.path.exists( params.output.phasematch_mtz ), 'The output file ({}) already exists. Please delete it before re-running.'.format( params.output.phasematch_mtz) merge = CommandManager('giant.mtz.merge') merge.add_command_line_arguments('label_suffix=incremental') merge.add_command_line_arguments(params.input.mtz) merge.add_command_line_arguments('output.mtz=' + params.output.merged_mtz) merge.add_command_line_arguments(params.settings.f_obs.split(',')) merge.add_command_line_arguments(params.settings.f_calc.split(',')) merge.run() merge.write_output(params.output.merging_log) if not os.path.exists(params.output.merged_mtz): raise Failure('giant.mtz.merge has failed to merge the mtz files') fo1, fo2 = params.settings.f_obs.split(',') fc1, fc2 = params.settings.f_calc.split(',') for i_2 in range(1, len(params.input.mtz) + 1): for i_1 in range(1, len(params.input.mtz) + 1): if i_1 == i_2: break match = CommandManager('cphasematch') match.add_command_line_arguments( ['-mtzin', params.output.merged_mtz]) match.add_command_line_arguments( ['-mtzout', params.output.phasematch_mtz]) match.add_command_line_arguments( ['-colin-fo', '{}-{},{}-{}'.format(fo1, i_1, fo1, i_1)]) match.add_command_line_arguments( ['-colin-fc-1', '{}-{},{}-{}'.format(fc1, i_1, fc1, i_1)]) match.add_command_line_arguments( ['-colin-fc-2', '{}-{},{}-{}'.format(fc2, i_2, fc2, i_2)]) match.run() march.write_output(params.output.phase_log_template + '-{}-{}.log'.format(i_1.i_2))
def create_asu_map(mapin, mapout): """Takes mapin and masks to the asymmetric unit""" # Masking object masker = CommandManager('mapmask') # Set input files masker.add_command_line_arguments(['mapin', mapin, 'mapout', mapout]) # Set stdin masker.add_standard_input(['XYZLIM ASU', 'END']) # Run! masker.run() # Report errors if masker.process.returncode != 0: raise RuntimeError( 'mapmask failed to create asu map from {!s}'.format(mapin)) # Return Command Managers for flexible handling of out & err return masker
def mask_map(mapin, maskpdb, mapout, border=1): """Takes mapin and masks around atoms in maskpdb""" # Masking object masker = CommandManager('mapmask') # Set input files masker.add_command_line_arguments( ['mapin', mapin, 'mapout', mapout, 'xyzin', maskpdb]) # Set stdin masker.add_standard_input(['BORDER {!s}'.format(border), 'END']) # Run! masker.run() # Report errors if masker.process.returncode != 0: raise RuntimeError('mapmask failed to mask map {!s}'.format(mapin)) # Return Command Managers for flexible handling of out & err return masker
def reset_pdb_file(pdbin, pdbout): """Resets the B-Factors in a file and removes anisotropy""" if not pdbout.endswith('.pdb'): pdbout = pdbout + '.pdb' if not os.path.exists(pdbin): raise IOError('pdbin does not exist! {!s}'.format(pdbin)) if os.path.exists(pdbout): raise Exception('pdbout already exists! {!s}'.format(pdbout)) pdbtemp = pdbout.replace('.pdb', '.temp.pdb') # Initialise Commander PDBCUR = CommandManager('pdbcur') # Set Command Arguments PDBCUR.add_command_line_arguments('XYZIN', pdbin, 'XYZOUT', pdbtemp) # Set inputs PDBCUR.add_standard_input(['NOANISOU', 'DELSOLVENT', 'END']) # run! PDBCUR.run() if not os.path.exists(pdbtemp): raise ExternalProgramError( 'PDBCUR has failed to remove anisotropy and delete solvent. {!s}\nOUT: {!s}\nERR: {!s}' .format(pdbin, PDBCUR.out, PDBCUR.err)) # Initialise Commander PDBSET = CommandManager('pdbset') # Set Command Arguments PDBSET.add_command_line_arguments('XYZIN', pdbtemp, 'XYZOUT', pdbout) # Set inputs PDBSET.add_standard_input(['BFACTOR', 'END']) # run! PDBSET.run() if not os.path.exists(pdbout): raise ExternalProgramError( 'PDBSET has failed to reset B-factors. {!s}\nOUT: {!s}\nERR: {!s}'. format(pdbtemp, PDBSET.out, PDBSET.err)) else: os.remove(pdbtemp) return pdbout
def isolate_residue_by_res_id(inpdb, outpdb, chain, resnum, model='*', inscode=''): """Isolate the residues identified by residue ids using pdbcur - i.e. '0/A/54.A/'""" if inscode: selection = '/{!s}/{!s}/{!s}.{!s}'.format(model, chain, resnum, inscode) else: selection = '/{!s}/{!s}/{!s}'.format(model, chain, resnum) PDBCUR = CommandManager('pdbcur') PDBCUR.add_command_line_arguments('XYZIN', inpdb, 'XYZOUT', outpdb) PDBCUR.add_standard_input(['lvresidue {!s}'.format(selection), 'END']) PDBCUR.run() return PDBCUR
def fft_mtz_to_map(mtz_file, map_file, cols): """Converts an MTZ Format File to a MAP File (using fft as default)""" # Initialise writer = CommandManager('fft') # Set Program Arguments writer.add_command_line_arguments('hklin', mtz_file, 'mapout', map_file) # Set Program Input writer.add_standard_input( ['LABIN F1={!s} PHI={!s}'.format(cols['F'], cols['P']), 'END']) # RUN! writer.run() # Check Output if writer.process.returncode != 0: print('\nOUT\n\n' + writer.out) print('\nERR\n\n' + writer.err) raise RuntimeError( 'fft failed to generate map from {!s}'.format(mtz_file)) return writer
def run_coot(script, graphical=False, noguano=True): """Runs coot with the provided script""" # Check that the script is valid (e.g. causes coot to exit at the end) validate_coot_script(script) # Stop coot droppings? coot_flags = ['--no-guano']*(noguano) # Run with/without graphics? if graphical: coot_flags.extend(['-script',script]) else: coot_flags.extend(['--no-graphics','-s',script]) # Initialise COOT = CommandManager('coot') # Load arguments COOT.add_command_line_arguments(*coot_flags) # Run! COOT.run() return COOT
def remove_residue_by_res_id(inpdb, outpdb, chain, resnum, model='*', inscode='', removeSolvent=False): """Remove the residues identified by res info using pdbcur - i.e. 'UNL'""" if inscode: selection = '/{!s}/{!s}/{!s}.{!s}'.format(model, chain, resnum, inscode) else: selection = '/{!s}/{!s}/{!s}'.format(model, chain, resnum) std_input = ['delresidue {!s}'.format(selection) ] + (removeSolvent) * ['delsolvent'] + ['END'] PDBCUR = CommandManager('pdbcur') PDBCUR.add_command_line_arguments('XYZIN', inpdb, 'XYZOUT', outpdb) PDBCUR.add_standard_input(std_input) PDBCUR.run() return PDBCUR
def merge_cif_libraries(incifs, outcif): """Take a list of cifs and merge into one cif""" assert isinstance(incifs, list), "'incifs' is not a list!" assert len(incifs) > 1, "'incifs' must be two or more files!" current = incifs.pop(0) to_be_deleted = [] for additional in incifs: # Create a file handle and path for the output temp_handle, temp_path = tempfile.mkstemp(suffix='.lib', prefix='libcheck_') to_be_deleted.append(temp_path) # Merge current and additional to temp_path LIBCHK = CommandManager('libcheck') LIBCHK.add_standard_input( '_DOC N', '_FILE_L {!s}'.format(current), '_FILE_L2 {!s}'.format(additional), '_FILE_O {!s}'.format(temp_path.replace('.lib', '')), '_END') LIBCHK.run() current = temp_path shutil.copy(current, outcif) for file in to_be_deleted: os.remove(file) assert os.path.exists(outcif), 'OUTPUT CIF DOES NOT EXIST! {!s}'.format( outcif) return outcif
def get_mtz_resolution(mtz_file): """Gets the max resolution from the file""" # Extract Contents of MTZ MTZDMP = CommandManager('mtzdmp') MTZDMP.add_command_line_arguments(mtz_file) MTZDMP.run() # Check for errors if MTZDMP.process.returncode != 0: raise RuntimeError( 'mtzdmp failed to read file {!s}:\nReturn: {!s}\nOut: {!s}'.format( mtz_file, MTZDMP.process.returncode, MTZDMP.output)) # Search for the Column Headings regex = re.compile('\* Resolution Range :.*\n.*\n.*\((.*)A \)\n') matches = regex.findall(MTZDMP.output) # Check for validity of matches assert matches, 'No Resolution Range found in MTZFile {!s}'.format( mtz_file) assert len( matches ) == 1, 'Too many matching lines found for Column Headings in MTZFile {!s}\n\t{!s}'.format( mtz_file, matches) # Return return map(float, matches[0].replace(' ', '').split('-'))
def run_xia2(img_dir, out_dir, method='dials', verbose=True): """Run xia2 on the images in img_dir, and put the results in out_dir""" assert method in ['2d','3d','3dii','dials'], 'Invalid method provided' assert os.path.exists(img_dir), 'Image directory does not exist' if not os.path.exists(out_dir): os.mkdir(out_dir) # Convert to absolute path to allow folder changing img_dir = os.path.abspath(img_dir) out_dir = os.path.abspath(out_dir) # Store current directory cur_dir = os.getcwd() try: # Output logfile xia2_log = os.path.join(out_dir, 'xia2.log') # Got to directory to run MLFSOM os.chdir(out_dir) xia2 = CommandManager('xia2') xia2.add_command_line_arguments('-'+method, img_dir) if verbose: print('Running xia2 on {}').format(img_dir) rc = xia2.run() if rc != 0: print('STDOUT:') print(xia2.output) print('STDERR:') print(xia2.error) with open(xia2_log, 'a') as fh: fh.write('==================================================>\n') fh.write('xia2 log\n') fh.write('==================================================>\n') fh.write(xia2.output+'\n') fh.write('==================================================>\n') fh.write('xia2 errors\n') fh.write('==================================================>\n') fh.write(xia2.error+'\n') fh.write('==================================================>\n') finally: # Change back to original directory os.chdir(cur_dir) return xia2
def phenix_find_tls_groups(pdb_file): cmd = CommandManager('phenix.find_tls_groups') cmd.add_command_line_arguments(pdb_file) #cmd.print_settings() ret_code = cmd.run() if ret_code != 0: print cmd.output print cmd.error raise Exception('Failed to determine TLS groups: {}'.format(' '.join( cmd.program))) regex = re.compile("refinement\.refine\.adp \{([\s\S]*?)\}") tls_command = regex.findall(cmd.output)[0] tls_selections = [ s.strip() for s in tls_command.split('tls =') if s.strip() ] return tls_selections
def run(params): # Identify any existing output directories current_dirs = sorted(glob.glob(params.output.dir_prefix + "*")) if not current_dirs: next_int = 1 else: current_nums = [ s.replace(params.output.dir_prefix, "") for s in current_dirs ] next_int = sorted(map(int, current_nums))[-1] + 1 # Create output directory name from int out_dir = params.output.dir_prefix + "{:04}".format(next_int) # Create output directory os.mkdir(out_dir) # Create log object log = Log( log_file=os.path.join(out_dir, params.output.out_prefix + ".quick-refine.log"), verbose=params.settings.verbose, ) # Report if current_dirs: log("Found existing refinement directories: \n\t{}".format( "\n\t".join(current_dirs))) log("") log("Creating new output directory: {}".format(out_dir)) # Validate input parameters log.subheading("Validating input parameters") assert params.input.pdb is not None, "No PDB given for refinement" assert params.input.mtz is not None, "No MTZ given for refinement" if os.path.islink(params.input.mtz): log("Converting mtz path to real path:") log("{} -> {}".format(params.input.mtz, os.path.realpath(params.input.mtz))) params.input.mtz = os.path.realpath(params.input.mtz) # Link input log("Copying/linking files to refinement folder") shutil.copy(params.input.pdb, os.path.abspath(os.path.join(out_dir, "input.pdb"))) rel_symlink(params.input.mtz, os.path.abspath(os.path.join(out_dir, "input.mtz"))) # Copy parameter file to output folder if params.input.params: shutil.copy(params.input.params, os.path.abspath(os.path.join(out_dir, "input.params"))) # Create output prefixes output_prefix = out_dir log("Real output file path prefixes: {}".format(output_prefix)) log("Link output file path prefixes: {}".format(params.output.link_prefix)) # Create command objects log.subheading("Preparing command line input for refinement program") # PHENIX if params.options.program == "phenix": cm = CommandManager("phenix.refine") # Command line args cm.add_command_line_arguments([params.input.pdb, params.input.mtz]) cm.add_command_line_arguments( ["output.prefix={}".format(output_prefix)]) if params.input.cif: cm.add_command_line_arguments(params.input.cif) if params.input.params and os.path.exists(params.input.params): cm.add_command_line_arguments([params.input.params]) # REFMAC elif params.options.program == "refmac": cm = CommandManager("refmac5") # Command line args cm.add_command_line_arguments( ["xyzin", params.input.pdb, "hklin", params.input.mtz]) cm.add_command_line_arguments([ "xyzout", output_prefix + ".pdb", "hklout", output_prefix + ".mtz" ]) if params.input.cif: for cif in params.input.cif: cm.add_command_line_arguments(["libin", cif]) # Standard input if params.input.params: cm.add_standard_input(open(params.input.params).read().split("\n")) cm.add_standard_input(["END"]) # Pass additional command line arguments? if params.input.args: cm.add_command_line_arguments(params.input.args) # Report log(str(cm)) log.bar() log("running refinement... ({})".format(cm.program[0])) out = cm.run() log.subheading("Refinement output") if not log.verbose: log("output written to log file ({} lines)".format( cm.output.count("\n"))) log("\n" + cm.output, show=False) if out != 0: log.subheading("Refinement Errors") log(cm.error) log.subheading("Post-processing output files") # Find output files try: real_pdb = os.path.join(output_prefix, params.output.out_prefix + ".pdb") real_mtz = os.path.join(output_prefix, params.output.out_prefix + ".mtz") print(real_pdb, "\n", real_mtz) except: log("Refinement has failed - output files do not exist") log("{}: {}".format(output_prefix + "*.pdb", glob.glob(output_prefix + "*.pdb"))) log("{}: {}".format(output_prefix + "*.mtz", glob.glob(output_prefix + "*.mtz"))) raise # List of links to make at the end of the run link_file_pairs = [ (real_pdb, params.output.link_prefix + ".pdb"), (real_mtz, params.output.link_prefix + ".mtz"), ] print(link_file_pairs) # Split conformations if params.options.split_conformations: params.split_conformations.settings.verbose = params.settings.verbose log.subheading("Splitting refined structure conformations") # Running split conformations out_files = split_conformations.split_conformations( filename=real_pdb, params=params.split_conformations, log=log) # Link output files to top for real_file in out_files: link_file = params.output.link_prefix + os.path.basename( real_file.replace(os.path.splitext(real_pdb)[0], "")) link_file_pairs.append([real_file, link_file]) # Link output files log.subheading("linking output files") for real_file, link_file in link_file_pairs: log("Linking {} -> {}".format(link_file, real_file)) if not os.path.exists(real_file): log("file does not exist: {}".format(real_file)) continue if os.path.exists(link_file) and os.path.islink(link_file): log("removing existing link: {}".format(link_file)) os.unlink(link_file) if not os.path.exists(link_file): rel_symlink(real_file, link_file) log.heading("finished - refinement")
def run_mlfsom(pdb_file, res_h, out_dir='mlfsom_out', n_images=180, osc=1.0, energy=12660, verbose=True): """Run MLFSOM on the given file.""" ftd_pre = ['1H87.pdb', 'example.com', 'example.mat', 'mlfsom.log', 'refined.pdb', 'pristine.mtz'] assert not os.path.exists(out_dir), 'output directory already exists!' assert os.path.exists(pdb_file) assert isinstance(n_images, int) # Store current directory cur_dir = os.getcwd() try: # Create a temporary directory for mlfsom to run in (and go to it) tmp_dir = tempfile.mkdtemp(prefix='mlfsom_') mlfsom_pdb = os.path.join(tmp_dir, 'refined.pdb') mlfsom_mtz = os.path.join(tmp_dir, 'pristine.mtz') mlfsom_log = os.path.join(tmp_dir, 'mlfsom.log') mlfsom_img = 'image_###.img' # Get the mlfsom tarball and move it to the temporary directory mlfsom_file = os.path.join(bamboo.resources.__path__[0], 'mlfsom.tar.gz') assert os.path.exists(mlfsom_file), 'MLFSOM tarball not found' shutil.copy(mlfsom_file, tmp_dir) mlfsom_file = os.path.join(tmp_dir, 'mlfsom.tar.gz') assert os.path.exists(mlfsom_file), 'MLFSOM tarball not in temporary directory' # Untar the file t = tarfile.open(mlfsom_file, 'r:gz') try: t.extractall(tmp_dir) finally: t.close() # Delete unnecessary files for f in ftd_pre: fp = os.path.join(tmp_dir, f) if os.path.exists(fp): os.remove(fp) # Move the input files in shutil.copy(pdb_file, mlfsom_pdb) # Got to directory to run MLFSOM os.chdir(tmp_dir) # Convert the pdb_file to structure factors ano_sfall = CommandManager('./ano_sfall.com') ano_sfall.add_command_line_arguments(os.path.basename(mlfsom_pdb)) ano_sfall.add_command_line_arguments('energy={}'.format(energy)) ano_sfall.add_command_line_arguments('{}A'.format(res_h)) if verbose: print('Running ./ano_sfall.com on {}').format(pdb_file) rc = ano_sfall.run() if rc != 0: print('STDOUT:') print(ano_sfall.output) print('STDERR:') print(ano_sfall.error) shutil.move('ideal_ano.mtz', mlfsom_mtz) with open(mlfsom_log, 'a') as fh: fh.write('==================================================>\n') fh.write('ano_sfall log\n') fh.write('==================================================>\n') fh.write(ano_sfall.output+'\n') fh.write('==================================================>\n') fh.write('ano_sfall errors\n') fh.write('==================================================>\n') fh.write(ano_sfall.error+'\n') fh.write('==================================================>\n') # Run MLFSOM on the resulting mtzfile mlfsom = CommandManager('./mlfsom.com') mlfsom.add_command_line_arguments(mlfsom_img) mlfsom.add_command_line_arguments('frames={}'.format(n_images)) mlfsom.add_command_line_arguments('osc={}'.format(osc)) if verbose: print('Running ./mlfsom.com on {}. This may take a while...').format(pdb_file) rc = mlfsom.run() if rc != 0: print('STDOUT:') print(mlfsom.output) print('STDERR:') print(mlfsom.error) with open(mlfsom_log, 'a') as fh: fh.write('==================================================>\n') fh.write('mlfsom log\n') fh.write('==================================================>\n') fh.write(mlfsom.output+'\n') fh.write('==================================================>\n') fh.write('mlfsom errors\n') fh.write('==================================================>\n') fh.write(mlfsom.error+'\n') fh.write('==================================================>\n') finally: # Change back to original directory os.chdir(cur_dir) # Delete temporary directory shutil.move(tmp_dir, out_dir) return ano_sfall, mlfsom
class BuilderObject(object): """Template Object for creating an Object to generate ligand restraints""" def __init__(self, time=True, verbose=True): self.allowed_args = allowed_builder_args self.ligname = DEFAULT_LIGAND_NAMES[0] # Settings self.time = time self.verbose = verbose self.runtime = -1.0 self.timeout = 1800 # Custom Init self._custom_init() def generate_ligand(self, ligsmile, outdir, outfile, flags=[]): """Generate ligand PDB and CIF from smile string""" # Prepare standard settings self._prepare_to_generate_ligand(ligsmile, outdir, outfile, flags) # Check to see if already run, and if not, run the custom part of the object - different for each program if os.path.exists(self.outpdb) and os.path.exists( self.outcif) and os.path.exists(self.outlog): if self.verbose: print('\tLigand already generated - DOING NOTHING') else: cmd_line_args, std_inpt_args = self._create_program_arguments( ligsmile, outdir, outfile, flags) # Initialise CommandManager self.builder = CommandManager(self.program) # Set Command-Line Args if cmd_line_args: self.builder.add_command_line_arguments(cmd_line_args) # Set Standard Input if std_inpt_args: self.builder.add_standard_input(std_inpt_args) # Set Parameters self.builder.set_timeout(timeout=self.timeout) # RUN self.builder.run() # Get runtime self.runtime = self.builder.runtime try: # Could add postprocess here pass finally: self.write_log_file() return self.outpdb, self.outcif, self.outlog def _prepare_to_generate_ligand(self, ligsmile, outdir, outfile, flags): """Set up the generic file names""" # Process outputfile if '/' in outfile: raise ValueError('outfile must be a file, not a path') # Record Template and Outdir self.outtemplate = os.path.join(outdir, outfile) self.outdir = outdir # Record Filenames self.outpdb = self.outtemplate + '.pdb' self.outcif = self.outtemplate + '.cif' self.outlog = self.outtemplate + '.log' def write_log_file(self): """Write the log file""" with open(self.outlog, 'w') as logfile: # Write out the input command logfile.write('\nCOMMAND\n\n') logfile.write('\n'.join(self.builder.cmd_line_args) + '\n') logfile.write('\nINPUT\n\n') logfile.write('\n'.join(self.builder.std_inp_lines) + '\n') # Write out & err logfile.write('\nSTDOUT\n\n') logfile.write(self.builder.output) logfile.write('\nSTDERR\n\n') logfile.write(self.builder.error)
class _refiner(object): program = None auto = True def __init__(self, pdb_file, mtz_file=None, cif_file=None, out_prefix=None, **kw_args): # Set defaults if not given if mtz_file is None: mtz_file = pdb_file.replace('.pdb', '.mtz') if out_prefix is None: out_prefix = os.path.splitext(pdb_file)[0] + '-refined' # Main files self.pdb_file = pdb_file self.mtz_file = mtz_file self.cif_file = cif_file # Eventual output prefix self.out_prefix = out_prefix self.out_pdb_file = self.out_prefix + '.pdb' self.out_mtz_file = self.out_prefix + '.mtz' self.out_log_file = self.out_prefix + '.log' # Validate input assert os.path.exists(self.pdb_file) assert os.path.exists(self.mtz_file) assert not os.path.exists( self.out_pdb_file), 'Output file already exists: {}'.format( self.out_pdb_file) assert not os.path.exists( self.out_mtz_file), 'Output file already exists: {}'.format( self.out_mtz_file) # Create temporary folder for refinement self.tmp_dir = tempfile.mkdtemp(prefix='refine-model-') self.tmp_pre = os.path.join(self.tmp_dir, 'refine') # Command object for refinement self.cmd = CommandManager(self.program) self.kw_args = kw_args # Setup, refine and post_process if self.auto is True: self.run() def run(self): """...run refinement amd export files""" self.setup() ret = self.refine() self.export() return ret def setup(self): raise Exception('Dummy class -- not implemented') def refine(self): """...run the refinement""" self.cmd.print_settings() return self.cmd.run() def export(self): """Copy files to output destination""" # Find pdb file in the output folder tmp_pdb = glob.glob(self.tmp_pre + '*.pdb') assert tmp_pdb, 'No refined files found: {}'.format(self.tmp_dir) tmp_pdb = tmp_pdb[0] tmp_mtz = tmp_pdb.replace('.pdb', '.mtz') assert os.path.exists(tmp_pdb) assert os.path.exists(tmp_mtz) # Copy to output folder shutil.copy(tmp_pdb, self.out_pdb_file) shutil.copy(tmp_mtz, self.out_mtz_file) assert os.path.exists(self.out_pdb_file) assert os.path.exists(self.out_mtz_file) # Write the log to the output log file self.cmd.write_output(self.out_log_file) # Delete temporary directory shutil.rmtree(self.tmp_dir)
def run(params): # Identify any existing output directories current_dirs = sorted(glob.glob(params.output.dir_prefix + '*')) if not current_dirs: next_int = 1 else: current_nums = [ s.replace(params.output.dir_prefix, '') for s in current_dirs ] next_int = sorted(map(int, current_nums))[-1] + 1 # Create output directory name from int out_dir = params.output.dir_prefix + '{:04}'.format(next_int) # Create output directory os.mkdir(out_dir) # Create log object log = Log(log_file=os.path.join( out_dir, params.output.out_prefix + '.quick-refine.log'), verbose=params.settings.verbose) # Report if current_dirs: log('Found existing refinement directories: \n\t{}'.format( '\n\t'.join(current_dirs))) log('') log('Creating new output directory: {}'.format(out_dir)) # Validate input parameters log.subheading('Validating input parameters') assert params.input.pdb is not None, 'No PDB given for refinement' assert params.input.mtz is not None, 'No MTZ given for refinement' if os.path.islink(params.input.mtz): log('Converting mtz path to real path:') log('{} -> {}'.format(params.input.mtz, os.path.realpath(params.input.mtz))) params.input.mtz = os.path.realpath(params.input.mtz) # Link input log('Copying/linking files to refinement folder') shutil.copy(params.input.pdb, os.path.abspath(os.path.join(out_dir, 'input.pdb'))) rel_symlink(params.input.mtz, os.path.abspath(os.path.join(out_dir, 'input.mtz'))) # Copy parameter file to output folder if params.input.params: shutil.copy(params.input.params, os.path.abspath(os.path.join(out_dir, 'input.params'))) # Create output prefixes output_prefix = os.path.join(out_dir, params.output.out_prefix) log('Real output file path prefixes: {}'.format(output_prefix)) log('Link output file path prefixes: {}'.format(params.output.link_prefix)) # Create command objects log.subheading('Preparing command line input for refinement program') # PHENIX if params.options.program == 'phenix': cm = CommandManager('phenix.refine') # Command line args cm.add_command_line_arguments([params.input.pdb, params.input.mtz]) cm.add_command_line_arguments( ['output.prefix={}'.format(output_prefix)]) if params.input.cif: cm.add_command_line_arguments(params.input.cif) if params.input.params and os.path.exists(params.input.params): cm.add_command_line_arguments([params.input.params]) # REFMAC elif params.options.program == 'refmac': cm = CommandManager('refmac5') # Command line args cm.add_command_line_arguments( ['xyzin', params.input.pdb, 'hklin', params.input.mtz]) cm.add_command_line_arguments([ 'xyzout', output_prefix + '.pdb', 'hklout', output_prefix + '.mtz' ]) if params.input.cif: for cif in params.input.cif: cm.add_command_line_arguments(['libin', cif]) # Standard input if params.input.params: cm.add_standard_input(open(params.input.params).read().split('\n')) cm.add_standard_input(['END']) elif params.options.program == "buster": cm = CommandManager('refine') # Command line arguments # inputs cm.add_command_line_arguments( ['-p', params.input.pdb, '-m', params.input.mtz, '-d', out_dir]) if params.input.cif: for cif in params.input.cif: cm.add_command_line_arguments(['-l', cif]) if params.input.params: cm.add_command_line_arguments(['-Gelly', params.input.params]) # Pass additional command line arguments? if params.input.args: cm.add_command_line_arguments(params.input.args) # Report log(str(cm)) log.bar() log('running refinement... ({})'.format(cm.program[0])) out = cm.run() log.subheading('Refinement output') if not log.verbose: log('output written to log file ({} lines)'.format( cm.output.count('\n'))) log('\n' + cm.output, show=False) if out != 0: log.subheading('Refinement Errors') log(cm.error) log.subheading('Post-processing output files') if params.options.program == "buster": log.subheading('Renaming buster output files') shutil.move(src=os.path.join(out_dir, 'refine.pdb'), dst=output_prefix + '.pdb') shutil.move(src=os.path.join(out_dir, 'refine.mtz'), dst=output_prefix + '.mtz') # Find output files try: real_pdb = glob.glob(output_prefix + '*.pdb')[0] real_mtz = glob.glob(output_prefix + '*.mtz')[0] except: log('Refinement has failed - output files do not exist') log('{}: {}'.format(output_prefix + '*.pdb', glob.glob(output_prefix + '*.pdb'))) log('{}: {}'.format(output_prefix + '*.mtz', glob.glob(output_prefix + '*.mtz'))) raise # List of links to make at the end of the run link_file_pairs = [(real_pdb, params.output.link_prefix + '.pdb'), (real_mtz, params.output.link_prefix + '.mtz')] # Split conformations if params.options.split_conformations: params.split_conformations.settings.verbose = params.settings.verbose log.subheading('Splitting refined structure conformations') # Running split conformations out_files = split_conformations.split_conformations( filename=real_pdb, params=params.split_conformations, log=log) # Link output files to top for real_file in out_files: link_file = params.output.link_prefix + os.path.basename( real_file.replace(os.path.splitext(real_pdb)[0], '')) link_file_pairs.append([real_file, link_file]) # Link output files log.subheading('linking output files') for real_file, link_file in link_file_pairs: log('Linking {} -> {}'.format(link_file, real_file)) if not os.path.exists(real_file): log('file does not exist: {}'.format(real_file)) continue if os.path.exists(link_file) and os.path.islink(link_file): log('removing existing link: {}'.format(link_file)) os.unlink(link_file) if not os.path.exists(link_file): rel_symlink(real_file, link_file) log.heading('finished - refinement')
def run(params): in_mtzs = params.input.mtz assert len(params.input.mtz) > 1, 'Need to provide at least one mtz files' # assert len(params.input.mtz) < 3, 'Need to provide at most two mtz files' out_mtz = params.output.mtz out_log = params.output.log ########################################### # COMMAND LINE COMMANDS ########################################### cm = CommandManager('cad') ########################################### # ITERATE THROUGH INPUT MTZS ########################################### for i_mtz, mtz in enumerate(in_mtzs): # Use numbering from 1 n_mtz = i_mtz + 1 # Create an mtz suffix if params.options.label_suffix == 'incremental': suffix = '-{}'.format(n_mtz) elif params.options.label_suffix == 'filename': suffix = '-{}'.format(os.path.splitext(os.path.basename(mtz))[0]) elif params.options.label_suffix == 'foldername': suffix = '-{}'.format(os.path.basename(os.path.dirname(mtz))) else: raise Exception('Not yet implemented, sorry') # Add to the command line cm.add_command_line_arguments(['hklin{}'.format(n_mtz), mtz]) # Select column labels cm.add_standard_input('labin file_number {0} {1}'.format( n_mtz, ' '.join([ 'E{0}={1}'.format(i + 1, c) for i, c in enumerate(params.options.column.label) ]))) cm.add_standard_input('labout file_number {0} {1}'.format( n_mtz, ' '.join([ 'E{0}={1}'.format(i + 1, c + suffix) for i, c in enumerate(params.options.column.label) ]))) ########################################### # OUTPUT FILES ########################################### cm.add_command_line_arguments(['hklout', out_mtz]) ########################################### # RUN ########################################### print 'Running CAD:' cm.print_settings() ret_code = cm.run() cm.write_output(log_file=out_log) if ret_code != 0: print '============================>' print 'Refmac returned with an error' print '============================>' print cm.output print '============================>' print cm.error print '============================>'
def score_with_edstats_to_list(mtz_file, pdb_file, f_label=None): """Scores residues against density, then returns list""" assert os.path.exists( mtz_file), 'MTZ file for edstats does not exist! {!s}'.format(mtz_file) assert os.path.exists( pdb_file), 'PDB file for edstats does not exist! {!s}'.format(mtz_file) # Create a file handle and path for the output temp_handle, temp_path = tempfile.mkstemp(suffix='.table', prefix='edstats_') # Collate summary of MTZ file m_summ = MtzSummary(mtz_file) # Use column labels if given if (f_label is not None) and (f_label not in m_summ.summary['colheadings']): raise Sorry( 'Selected f_label ({}) not found in mtz file ({}) -- mtz contains columns {}' .format(f_label, mtz_file, m_summ.summary['colheadings'])) # else guess the labels in the mtzfile else: f_label = m_summ.label.f # Check for f_label if not f_label: raise Sorry( 'No F label selected/found in mtz file: {!s} -- mtz contains columns {}' .format(mtz_file, m_summ.summary['colheadings'])) # Run EDSTATS on the files try: # Initialise Command Manager to run edstats command = CommandManager('edstats.pl') command.add_command_line_arguments([ '-hklin', mtz_file, '-xyzin', pdb_file, '-output', temp_path, '-noerror', '-flabel', f_label ]) command.set_timeout(timeout=600) command.run() # Read the output with os.fdopen(temp_handle) as f: output = f.read().strip().replace('\r\n', '\n').replace('\r', '\n').splitlines() command.file_output = output finally: os.remove(temp_path) # Process the output header if output: # Check header and then remove the first three columns header = output.pop(0).split() assert header[:3] == [ 'RT', 'CI', 'RN' ], 'edstats output headers are not as expected! {!s}'.format(output) num_fields = len(header) header = header[3:] else: header = [] # List to be returned outputdata = [] # Process the rest of the data for line in output: line = line.strip() if not line: continue fields = line.split() if len(fields) != num_fields: raise ValueError( "Error Parsing EDSTATS output: Header & Data rows have different numbers of fields" ) # Get and process the residue information - TODO CI column can include alternate conformer?! TODO residue, chain, resnum = fields[:3] try: resnum = int(resnum) inscode = ' ' except ValueError: inscode = resnum[-1:] resnum = int(resnum[:-1]) # Remove the processed columns fields = fields[3:] # Process the other columns (changing n/a to None and value to int) for i, x in enumerate(fields): if x == 'n/a': fields[i] = None else: try: fields[i] = int(x) except ValueError: try: fields[i] = float(x) except ValueError: pass outputdata.append([(residue, chain, resnum, inscode), fields]) return outputdata, header, command