def test_prepare_work_dir_def(self): """ Test default behaviour, create unique tmp dir in system temp. """ path = prepare_work_dir() self.tempdirs.append(path) self.assertTrue(os.path.isdir(path)) self.assertTrue(os.access(path, os.W_OK))
def test_prepare_work_dir_suffix(self): """ Test creation unique temp dir with 'suffix' in basename. """ path = prepare_work_dir(suffix='-user') self.tempdirs.append(path) self.assertTrue(os.path.isdir(path)) self.assertTrue(os.path.basename(path).endswith('-user')) self.assertTrue(os.access(path, os.W_OK))
def test_prepare_work_dir_prefix(self): """ Test creation unique temp dir with 'prefix' in basename. """ path = prepare_work_dir(prefix='docking-') self.tempdirs.append(path) self.assertTrue(os.path.isdir(path)) self.assertTrue(os.path.basename(path).startswith('docking-')) self.assertTrue(os.access(path, os.W_OK))
def run(self, mol, mode='complete', input_format='mol2'): """ Run SMARTCyp predictions Runs a SMARTCyp prediction for molecule `mol` in a system temporary directory and returns the content of the prediction .csv file as a dictionary. :param mol: molecule to run SPORES on :type mol: :py:str :param mode: SPORES execution mode :type mode: :py:str :param input_format: Input structure format :type input_format: :py:str :return: SPORES processed structure :rtype: :py:dict """ # Create a working directory self.workdir = prepare_work_dir(path=self.base_work_dir, prefix='spores-') self.log.info('Created docking directory {0}'.format(self.workdir)) if not os.path.exists(self.exec_path): self.log.error('Spores executable not available at: {0}'.format(self.exec_path)) self.delete() return None # Copy files to working directory input_file = 'structure.{0}'.format(input_format) output_file = 'structure_{0}.mol2'.format(mode) with open(os.path.join(self.workdir, input_file), 'w') as protein_file: protein_file.write(mol) # Build and run SPORES CMD self.cmd_runner([self.exec_path, '--mode', mode, input_file, output_file]) output_file_path = os.path.join(self.workdir, output_file) if os.path.isfile(output_file_path): result = {'extension': output_file_path.split('.')[-1], 'path': output_file_path, 'encoding': 'utf8'} with open(output_file_path, 'r') as spores_output: result['content'] = spores_output.read() return result else: self.log.error('SPORES failed to create output file {0}'.format(output_file)) self.delete() return None
def test_prepare_work_dir_create(self): """ Test creation of unique temp dir in custom base dir """ to_create = os.path.join(FILEPATH, 'tmp_user_dir') path = prepare_work_dir(path=to_create) self.tempdirs.append(to_create) self.assertEqual(os.path.dirname(path), to_create) self.assertTrue(os.path.isdir(path)) self.assertTrue(os.access(path, os.W_OK))
def __init__(self, log=logger, base_work_dir=None): """ Implement class __init__ :param log: external logger instance :type log: :py:logging :param base_work_dir: base directory for unique docking results dirs. :type base_work_dir: :py:str """ self.log = log # Make a temporary directory self.workdir = prepare_work_dir(path=base_work_dir, prefix='smartcyp-') self.results = None
def run(self, protein, ligand, mode='screen'): """ Run a PLANTS docking for a given protein and ligand in mol2 format in either 'screen' or 'rescore' mode. A docking run requires the following PLANTS configuration arguments to be defined: * exec_path: path to the PLANTS executable * workdir: a working directory to write docking results to * bindingsite_center: target ligand binding site in the protein defined as a 3D coordinate The `run` function will exit if any of these requirements are not resolved. The PLANTS_CONF_FILE_TEMPLATE serves as a template where option values are replaced by format placeholders with the same name as the keys in the configuration dictionary. .. note:: the PLANTS write_multi_mol2 parameter is turned off by default to enable seperate clustering and result retrieval by the user. :param protein: protein 3D structure in mol2 format :type protein: str :param ligand: ligand 3D structure in mol2 format :type ligand: str :param mode: PLANTS execution mode as either virtual screening 'screen' or rescoring 'rescore' :type mode: str :return: boolean to indicate successful docking :rtype: bool """ # Check required PLANTS configuration arguments exec_path = self.config.get('exec_path') if not os.path.exists(exec_path): raise MDStudioException( 'Plants executable not available at: {0}'.format(exec_path)) if not os.access(exec_path, os.X_OK): raise MDStudioException( 'Plants executable {0} does not have exacutable permissions'. format(exec_path)) if sum(self.config['bindingsite_center']) == 0 or len( self.config['bindingsite_center']) != 3: raise MDStudioException( 'Malformed binding site center definition: {0}'.format( self.config['bindingsite_center'])) # Create a working directory self.workdir = prepare_work_dir(path=self.base_work_dir, prefix='docking-') self.log.info('Created docking directory {0}'.format(self.workdir)) # Copy files to working directory if os.path.isfile(protein): self.config['protein_file'] = protein else: with open(os.path.join(self.workdir, 'protein.mol2'), 'w') as protein_file: protein_file.write(protein) self.config['protein_file'] = 'protein.mol2' if os.path.isfile(ligand): self.config['ligand_file'] = ligand else: with open(os.path.join(self.workdir, 'ligand.mol2'), 'w') as ligand_file: ligand_file.write(ligand) self.config['ligand_file'] = 'ligand.mol2' lig_atm_count = atom_count( os.path.join(self.workdir, self.config['ligand_file'])) prot_atm_count = atom_count( os.path.join(self.workdir, self.config['protein_file'])) if lig_atm_count > prot_atm_count: self.delete() raise MDStudioException( 'Ligand structure contains more atoms than protein structure. Swapped input?' ) # Write PLANTS configuration file conf_file = os.path.join(self.workdir, 'plants.config') with open(conf_file, 'w') as conf: conf.write(PLANTS_CONF_FILE_TEMPLATE.format(**self.config)) success = self.cmd_runner([exec_path, '--mode', mode, 'plants.config']) if not success or not len( glob.glob(os.path.join(self.workdir, '*_entry_*_conf_*.mol2'))): success = False self.delete() return success