Пример #1
0
    def get_conformer_rmsd(mol: RDKitMol) -> np.ndarray:
        """
    Calculate conformer-conformer RMSD.

    Parameters
    ----------
    mol: rdkit.Chem.rdchem.Mol
      RDKit Mol object

    Returns
    -------
    rmsd: np.ndarray
      A conformer-conformer RMSD value. The shape is `(NumConformers, NumConformers)`
    """
        try:
            from rdkit.Chem import AllChem
        except ModuleNotFoundError:
            raise ValueError("This function requires RDKit to be installed.")

        rmsd = np.zeros((mol.GetNumConformers(), mol.GetNumConformers()),
                        dtype=float)
        for i, ref_conf in enumerate(mol.GetConformers()):
            for j, fit_conf in enumerate(mol.GetConformers()):
                if i >= j:
                    continue
                rmsd[i, j] = AllChem.GetBestRMS(mol, mol, ref_conf.GetId(),
                                                fit_conf.GetId())
                rmsd[j, i] = rmsd[i, j]
        return rmsd
Пример #2
0
    def generate_conformers(self, mol: RDKitMol) -> RDKitMol:
        """
    Generate conformers for a molecule.

    This function returns a copy of the original molecule with embedded
    conformers.

    Parameters
    ----------
    mol: rdkit.Chem.rdchem.Mol
      RDKit Mol object

    Returns
    -------
    mol: rdkit.Chem.rdchem.Mol
      A new RDKit Mol object containing the chosen conformers, sorted by
      increasing energy.
    """

        # initial embedding
        mol = self.embed_molecule(mol)
        if not mol.GetNumConformers():
            msg = 'No conformers generated for molecule'
            if mol.HasProp('_Name'):
                name = mol.GetProp('_Name')
                msg += ' "{}".'.format(name)
            else:
                msg += '.'
            raise RuntimeError(msg)

        # minimization and pruning
        self.minimize_conformers(mol)
        mol = self.prune_conformers(mol)

        return mol
Пример #3
0
    def prune_conformers(self, mol: RDKitMol) -> RDKitMol:
        """
    Prune conformers from a molecule using an RMSD threshold, starting
    with the lowest energy conformer.

    Parameters
    ----------
    mol: rdkit.Chem.rdchem.Mol
      RDKit Mol object

    Returns
    -------
    new_mol: rdkit.Chem.rdchem.Mol
      A new rdkit.Chem.rdchem.Mol containing the chosen conformers, sorted by
      increasing energy.
    """
        try:
            from rdkit import Chem
        except ModuleNotFoundError:
            raise ValueError("This function requires RDKit to be installed.")

        if self.rmsd_threshold < 0 or mol.GetNumConformers() <= 1:
            return mol
        energies = self.get_conformer_energies(mol)
        rmsd = self.get_conformer_rmsd(mol)

        sort = np.argsort(energies)  # sort by increasing energy
        keep: List[float] = []  # always keep lowest-energy conformer
        discard = []
        for i in sort:
            # always keep lowest-energy conformer
            if len(keep) == 0:
                keep.append(i)
                continue

            # discard conformers after max_conformers is reached
            if len(keep) >= self.max_conformers:
                discard.append(i)
                continue

            # get RMSD to selected conformers
            this_rmsd = rmsd[i][np.asarray(keep, dtype=int)]

            # discard conformers within the RMSD threshold
            if np.all(this_rmsd >= self.rmsd_threshold):
                keep.append(i)
            else:
                discard.append(i)

        # create a new molecule to hold the chosen conformers
        # this ensures proper conformer IDs and energy-based ordering
        new_mol = Chem.Mol(mol)
        new_mol.RemoveAllConformers()
        conf_ids = [conf.GetId() for conf in mol.GetConformers()]
        for i in keep:
            conf = mol.GetConformer(conf_ids[i])
            new_mol.AddConformer(conf, assignId=True)
        return new_mol