def protonate(self, reprotonate=False, babel_parameters=None, rdkit_parameters=None): """ Protonates the ligand using OpenBabel. Parameters ---------- reprotonate : bool Whether to reprotonate an already protonated ligand. babel_parameters : dict Keyword arguments to be passed to ProtoCaller.Wrappers.babelwrapper rdkit_parameters : dict Keyword arguments to be passed to ProtoCaller.Wrappers.rdkitwrapper """ with self.workdir: if babel_parameters is None: babel_parameters = {} babel_parameters = {"pH": 7.0, **babel_parameters} if rdkit_parameters is None: rdkit_parameters = {} if self.protonated and not reprotonate: _logging.info("Ligand %s is already protonated." % self.name) else: filename_temp = _rdkit.saveFromRdkit(self.molecule, filename="%s.mol" % self.name) # here we use PDB because of parser differences between OpenBabel and RDKit concerning mol and mol2 files self.protonated_filename = _babel.babelTransform( filename_temp, "pdb", **babel_parameters) _os.remove(filename_temp) self.molecule = _rdkit.openFileAsRdkit( self.protonated_filename, removeHs=False, **rdkit_parameters)
def alignToEachOther(self, output_filename=None, realign=False, **kwargs): """ Aligns the second ligand to the first ligand. Parameters ---------- output_filename : str The name of the output file. None uses the default value. realign : bool Whether to realign an already aligned ligand. kwargs Keyword arguments to pass to ProtoCaller.Wrappers.rdkitwrapper.alignTwoMolecules. Returns ------- morph : BioSimSpace.System The mixed topology object. mcs : [tuple] The maximum common substructure of the two molecules. """ if self.current_ref in self._morph.keys() and not realign: _logging.info("Morph %s is already aligned to a reference" % self.name) return if output_filename is None: _stdio.stdout_stderr()(self.ligand1.parametrise)(reparametrise=False) _stdio.stdout_stderr()(self.ligand2.parametrise)(reparametrise=False) output_filename = "{}_aligned_{}.{}".format(self.ligand2.name, self.name, self.ligand2.parametrised_files[1].split(".")[-1]) if "two_way_matching" not in kwargs.keys(): kwargs["two_way_matching"] = True if self.current_ref is None: self._ligand1_molecule[None] = self.ligand1.molecule self._ligand1_coords[None] = self.ligand1.parametrised_files[1] lig1_temp = self._ligand1_molecule[self.current_ref] lig2_temp = _copy.deepcopy(self.ligand2.molecule) self._ligand2_molecule[self.current_ref], mcs = _rdkit.alignTwoMolecules(lig1_temp, lig2_temp, **kwargs) self._ligand2_coords[self.current_ref] = _os.path.abspath( _rdkit.saveFromRdkit(self._ligand2_molecule[self.current_ref], output_filename)) # load the shifted ligands into BioSimSpace ligand1_BSS = _BSS.IO.readMolecules(self.parametrised_files1).getMolecules()[0] ligand2_BSS = _BSS.IO.readMolecules(self.parametrised_files2).getMolecules()[0] # translate RDKit mapping into BioSimSpace mapping mapping = {} indices_1 = [atom.index() for atom in ligand1_BSS._sire_object.edit().atoms()] indices_2 = [atom.index() for atom in ligand2_BSS._sire_object.edit().atoms()] for idx1, idx2 in mcs: mapping[indices_1[idx1]] = indices_2[idx2] # finally create morph self._morph[self.current_ref] = _BSS.Align.merge( ligand1_BSS, ligand2_BSS, mapping=mapping, allow_ring_breaking=True) return self._morph[self.current_ref], mcs
def alignToReference(self, ref, output_filename=None, realign=False, **kwargs): """ Aligns the first ligand to a reference ligand. Parameters ---------- ref : ProtoCaller.Ensemble.Ligand.Ligand The reference ligand. output_filename : str The name of the output file. None uses the default value. realign : bool Whether to realign an already aligned ligand. kwargs Keyword arguments to pass to ProtoCaller.Wrappers.rdkitwrapper.alignTwoMolecules. Returns ------- mcs : [tuple] The maximum common substructure of the two molecules. """ self.current_ref = ref if ref in self._ligand1_molecule.keys( ) and ref in self._ligand1_coords.keys() and not realign: _logging.info("Morph %s is already aligned to a reference" % self.name) return if output_filename is None: self.ligand1.parametrise(reparametrise=False) output_filename = "{}_aligned_{}.{}".format( self.ligand1.name, self.name, self.ligand1.parametrised_files[1].split(".")[-1]) if "two_way_matching" not in kwargs.keys(): kwargs["two_way_matching"] = False lig_temp = _copy.deepcopy(self.ligand1.molecule) self._ligand1_molecule[ref], mcs = _rdkit.alignTwoMolecules( ref.molecule, lig_temp, **kwargs) self._ligand1_coords[ref] = _rdkit.saveFromRdkit( self._ligand1_molecule[ref], output_filename) return mcs
def __init__(self, input, parametrised_files=None, name=None, protonated=False, minimise=None, workdir="."): self.name = name self.workdir = _fileio.Dir(workdir) self.minimise = minimise # always set protonated to False and if a valid protonated file is given it is automatically set to True self.protonated_filename = None with self.workdir: if parametrised_files: self.molecule = _rdkit.openAsRdkit(parametrised_files, removeHs=False, minimise=False, template=input) self.protonated_filename = _rdkit.saveFromRdkit( self.molecule, "{}.pdb".format(name)) elif isinstance(input, str): if _os.path.exists(input): if protonated: self.protonated_filename = input else: self.molecule = _rdkit.openAsRdkit(input, minimise=minimise) else: self.string = input elif isinstance(input, _rdchem.Mol): self.molecule = input else: raise TypeError( "Need a SMILES, InChI string, filename or an RDKit object as an input" ) self.parametrised_files = parametrised_files self.minimise = False
def amberWrapper(params, filename, molecule_type, id=None, charge=None, *args, **kwargs): """ Parametrises an input file according to AMBER force field. Parameters ---------- params : ProtoCaller.Parametrise.Params Force field parameters. filename : str Name of the input file. molecule_type : str The type of the molecule. One of: "protein", "ligand", "cofactor", "water", "simple_anion", "complex_anion", "simple_cation", "complex_cation". id : str The name of the molecule. Default: equal to molecule_type. charge : bool The net charge of the molecule. Default: automatic detection by antechamber. args Positional arguments to be passed to the relevant wrapper. kwargs Keyword arguments to be passed to the relevant wrapper. Returns ------- files : [str] The output parametrised file(s). If there is more than one file, the first one is always the topology file and the second one - the coordinate file. """ if id is None: id = molecule_type force_fields, files, param_files = [], [filename], [] if molecule_type == "protein": force_fields = [params.protein_ff, params.water_ff] elif molecule_type in ["water", "simple_anion", "simple_cation"]: force_fields = [params.water_ff] elif molecule_type == "complex_anion": _warnings.warn( "AMBER parametrisation failed: polyatomic anions not supported") return elif molecule_type == "complex_cation": _warnings.warn( "AMBER parametrisation failed: transition metals not supported") return elif molecule_type == "cofactor": if params.water_ff != "tip3p" or params.protein_ff != "ff99SB": _warnings.warn("All cofactors have been parametrised for use with " "the ff99SB protein force field and the TIP3P " "water model. Be careful when using these " "parameters with %s" % params.water_ff.upper()) files = [] force_fields = [params.protein_ff, params.ligand_ff] param_files = _glob.glob("%s/shared/amber-parameters/cofactors/%s.*" % (_PC.HOMEDIR, id)) # here we override the default parametrisation behaviour for cofactors parametrised_files = runTleap(force_fields=force_fields, files=files, param_files=param_files, id=id, *args, **kwargs) filebase = _os.path.splitext(filename)[0] topol = "{}.prmtop".format(filebase) _os.rename(parametrised_files[0], topol) parametrised_files[0] = topol # convert the parametrised file into PDB and load in RDKit ref = _rdkit.openAsRdkit(filename, removeHs=False) mol = _pmd.openFilesAsParmed(parametrised_files) pdb_file = _pmd.saveFilesFromParmed(mol, [filename], overwrite=True)[0] mol = _rdkit.openAsRdkit(pdb_file, removeHs=False) # align the parametrised file to the molecule and overwrite # previous coordinates mol, mcs = _stdio.stdout_stderr()(_rdkit.alignTwoMolecules) \ (ref, mol, two_way_matching=True, mcs_parameters=dict(atomCompare="elements")) if min(mol.GetNumAtoms(), ref.GetNumAtoms()) != len(mcs): _warnings.warn("The cofactor {} does not perfectly match the " "AMBER parameter file. Please check your " "molecule.".format(id)) _os.remove(parametrised_files[1]) coord = "{}.inpcrd".format(filebase) parametrised_files[1] = _rdkit.saveFromRdkit(mol, coord) return parametrised_files elif molecule_type == "ligand": force_fields = [params.ligand_ff] files = [runAntechamber(params.ligand_ff, filename, charge=charge)] param_files = [runParmchk(params.ligand_ff, files[0])] else: raise ValueError("Value %s for molecule_type not supported " % molecule_type) return runTleap(force_fields=force_fields, files=files, param_files=param_files, id=id, *args, **kwargs)