def test_PDB_residue_name(self): """ It tests the PDB residue name and checks for consistency with Molecule tag. """ def check_residue_name(name): """Check if residue names are valid in the output PDB file""" with open('molecule.pdb') as f: for line in f: if line.startswith('HETATM'): assert line[17:20] == name, 'Unexpected residue name' ligand_path = get_data_file_path('ligands/BNZ.pdb') # Checking tag assignation from PDB molecule = Molecule(ligand_path) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): assert molecule.tag == 'BNZ', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('BNZ') # Checking set_tag() function molecule = Molecule(ligand_path) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): molecule.set_tag('TAG') assert molecule.tag == 'TAG', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('TAG') # Checking default tag assignment from SMILES molecule = Molecule(smiles='c1ccccc1') with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): assert molecule.tag == 'UNK', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('UNK') # Checking custom tag assignment from SMILES molecule = Molecule(smiles='c1ccccc1', tag='BEN') with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): assert molecule.tag == 'BEN', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('BEN') # Checking second custom tag assignment from SMILES molecule = Molecule(smiles='c1ccccc1') with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): molecule.set_tag('BNZ') assert molecule.tag == 'BNZ', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('BNZ')
def test_offpele_default_call(self): LIGAND_PATH = 'ligands/BNZ.pdb' ligand_path = get_data_file_path(LIGAND_PATH) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): run_offpele(ligand_path, output=tmpdir)
def test_offpele_default_call(self): """ It checks the default call of offpele's main function. """ LIGAND_PATH = 'ligands/BNZ.pdb' ligand_path = get_data_file_path(LIGAND_PATH) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): run_offpele(ligand_path, output=tmpdir)
def test_offpele_custom_call(self): LIGAND_PATH = 'ligands/BNZ.pdb' ligand_path = get_data_file_path(LIGAND_PATH) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): run_offpele(ligand_path, forcefield=FORCEFIELD_NAME, resolution=10, charges_method='gasteiger', output=tmpdir, with_solvent=True, as_datalocal=True)
def get_OPLS_parameters(self, molecule): """ It calls Schrodinger's ffld_server to parameterize a molecule with OPLS. .. todo :: * Review PlopRotTemp's atom type fixes. Should we apply them here? Parameters ---------- molecule : an offpele.topology.Molecule The offpele's Molecule object Returns ------- OPLS_params : an OPLSParameters object The set of lists of parameters grouped by parameter type. Thus, the dictionary has the following keys: atom_names, atom_types, charges, sigmas, epsilons, SGB_radii, vdW_radii, gammas, and alphas """ ffld_server_exec = self.path_to_ffld_server() with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): self._rdkit_toolkit_wrapper.to_pdb_file( molecule, tmpdir + '/molecule.pdb') subprocess.check_output([ ffld_server_exec, "-ipdb", "molecule.pdb", "-version", "14", "-print_parameters", "-out_file", "parameters.txt" ]) OPLS_params = self._parse_parameters('parameters.txt') self._add_solvent_parameters(OPLS_params) return OPLS_params
def compute_partial_charges(self, molecule, method='am1bcc'): """ It computes the partial charges using antechamber. Parameters ---------- molecule : an offpele.topology.Molecule The offpele's Molecule object method : str The name of the method to use. One of ['gasteiger', 'am1bcc']. If None, 'am1bcc' will be used Returns ------- charges : simtk.unit.Quantity The array of partial charges Raises ------ ChargeMethodUnavailableError if the requested charge method can not be handled by this toolkit ChargeCalculationError if the charge method is supported by this toolkit, but fails """ SUPPORTED_CHARGE_METHODS = { 'am1bcc': { 'antechamber_keyword': 'bcc' }, 'gasteiger': { 'antechamber_keyword': 'gas' } } if method not in SUPPORTED_CHARGE_METHODS: raise ChargeMethodUnavailableError( 'partial_charge_method ' + '{} is not available from '.format(method) + 'AmberToolsToolkitWrapper. Available charge methods are ' + list(SUPPORTED_CHARGE_METHODS.keys())) off_molecule = molecule.off_molecule with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): net_charge = off_molecule.total_charge / \ unit.elementary_charge self._rdkit_toolkit_wrapper.to_sdf_file( molecule, tmpdir + '/molecule.sdf') subprocess.check_output([ "antechamber", "-i", "molecule.sdf", "-fi", "sdf", "-o", "charged.ac", "-fo", "ac", "-pf", "yes", "-dr", "n", "-c", SUPPORTED_CHARGE_METHODS[method]['antechamber_keyword'], "-nc", str(net_charge) ]) # Write out just charges subprocess.check_output([ "antechamber", "-dr", "n", "-i", "charged.ac", "-fi", "ac", "-o", "charged2.ac", "-fo", "ac", "-c", "wc", "-cf", "charges.txt", "-pf", "yes" ]) if not os.path.exists('charges.txt'): # TODO: copy files into local directory to aid debugging? raise ChargeCalculationError( "Antechamber/sqm partial charge calculation failed on " "molecule {} (SMILES {})".format( off_molecule.name, off_molecule.to_smiles())) # Read the charges with open('charges.txt', 'r') as infile: contents = infile.read() text_charges = contents.split() charges = np.zeros([off_molecule.n_atoms], np.float64) for index, token in enumerate(text_charges): charges[index] = float(token) charges = unit.Quantity(charges, unit.elementary_charge) assert len(charges) == len(molecule.rdkit_molecule.GetAtoms()), \ 'Partial charge computation failed as the length of ' \ + 'resulting partial charges does not match with the ' \ + 'number of atoms in molecule' return charges
def test_default_output_paths(self): """ It checks the default output paths that are used for each parameter file from offpele. """ def from_PosixPath_to_string(paths): """ Convert PosixPaths to strings """ return map(str, paths) molecule = Molecule(smiles='c1ccccc1', name='benzene', tag='BNZ') rotlib_path, impact_path, solvent_path = \ handle_output_paths(molecule, '', False) # Convert PosixPaths to strings rotlib_path, impact_path, solvent_path = map( str, [rotlib_path, impact_path, solvent_path]) assert rotlib_path == 'BNZ.rot.assign', 'Unexpected default ' \ + 'rotamer library path' assert impact_path == 'bnzz', 'Unexpected default Impact ' \ + 'template path' assert solvent_path == 'ligandParams.txt', 'Unexpected default ' \ + 'solvent parameters path' with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): # To avoid the complain about unexistent folder os.mkdir('output') rotlib_path, impact_path, solvent_path = \ handle_output_paths(molecule, 'output', False) # Convert PosixPaths to strings rotlib_path, impact_path, solvent_path = map( str, [rotlib_path, impact_path, solvent_path]) assert rotlib_path == 'output/BNZ.rot.assign', 'Unexpected default ' \ + 'rotamer library path' assert impact_path == 'output/bnzz', 'Unexpected default Impact ' \ + 'template path' assert solvent_path == 'output/ligandParams.txt', 'Unexpected ' \ + 'default solvent parameters path' rotlib_path, impact_path, solvent_path = \ handle_output_paths(molecule, '', True) # Convert PosixPaths to strings rotlib_path, impact_path, solvent_path = map( str, [rotlib_path, impact_path, solvent_path]) assert rotlib_path == 'DataLocal/LigandRotamerLibs/' \ + 'BNZ.rot.assign', 'Unexpected default rotamer library path' assert impact_path == 'DataLocal/Templates/OFF/Parsley/' \ + 'HeteroAtoms/bnzz', 'Unexpected default Impact template' assert solvent_path == 'DataLocal/OBC/ligandParams.txt', \ 'Unexpected default solvent parameters path' with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): # To avoid the complain about unexistent folder os.mkdir('output') rotlib_path, impact_path, solvent_path = \ handle_output_paths(molecule, 'output', True) # Convert PosixPaths to strings rotlib_path, impact_path, solvent_path = map( str, [rotlib_path, impact_path, solvent_path]) assert rotlib_path == 'output/DataLocal/LigandRotamerLibs/' \ + 'BNZ.rot.assign', 'Unexpected default rotamer library path' assert impact_path == 'output/DataLocal/Templates/OFF/Parsley/' \ + 'HeteroAtoms/bnzz', 'Unexpected default Impact template path' assert solvent_path == 'output/DataLocal/OBC/ligandParams.txt', \ 'Unexpected default solvent parameters path'