def generate_conformers(rdkit_mol: Chem.Mol, conformer_no: int) -> List[np.ndarray]: """ Generate a set of conformers for the molecule including the input conformer. Args: rdkit_mol: A complete Chem.Mol instance of a molecule. conformer_no: The number of conformers made for the molecule return: A list of conformer position arrays """ AllChem.EmbedMultipleConfs( rdkit_mol, numConfs=conformer_no, randomSeed=1, clearConfs=False, useBasicKnowledge=True, pruneRmsThresh=1, enforceChirality=True, ) positions = rdkit_mol.GetConformers() return [conformer.GetPositions() for conformer in positions]
def prune_conformers( mol: Chem.Mol, energies: list, rmsd_threshold: float ) -> (Chem.Mol, list): """ Adopted from: https://github.com/skearnes/rdkit-utils/blob/master/rdkit_utils/conformers.py Prune conformers from a molecule using an RMSD threshold, starting with the lowest energy conformer. Parameters ---------- mol : RDKit Mol Molecule. Returns ------- A new RDKit Mol containing the chosen conformers, sorted by increasing energy. """ from typing import List rmsd = get_conformer_rmsd(mol) sort = np.argsort( [x.value_in_unit(unit.kilocalorie_per_mole) for x in energies] ) # sort by increasing energy keep: List[int] = [] # always keep lowest-energy conformer discard: List[int] = [] for i in sort: # always keep lowest-energy conformer if len(keep) == 0: keep.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 >= 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()] filtered_energies = [] logger.debug(f"keep: {keep}") for i in keep: logger.debug(i) conf = mol.GetConformer(conf_ids[i]) filtered_energies.append(energies[i]) new_mol.AddConformer(conf, assignId=True) return new_mol, filtered_energies
def generate_conformers(rdkit_mol: Chem.Mol, conformer_no=10) -> List[np.ndarray]: """ Generate a set of x conformers of the molecule :param conformer_no: The amount of conformers made for the molecule :param rdkit_mol: The name of the input file :return: A list of conformer position arrays """ AllChem.EmbedMultipleConfs(rdkit_mol, numConfs=conformer_no) positions = rdkit_mol.GetConformers() return [conformer.GetPositions() for conformer in positions]
def draw(mol: Chem.Mol, energies: list = []) -> interact: """Make a drawing of all conformers in 3d :param mol: rdkit molecule :type mol: rdkit.Chem.Mol :param energies: list of conformer energies :type energies: list :return: interact 3D object """ p = py3Dmol.view(width=400, height=400) return interact(_graph_conf, m=fixed(mol), p=fixed(p), confId=[c.GetId() for c in mol.GetConformers()], energies=fixed(energies))
def extract_from_rdmol(mol: Chem.Mol) -> tuple: """Extract information from RDKit Mol object with conformers. :param mol: rdkit molecule :type mol: rdkit.Chem.Mol :return: tuple(elements, conformer_coordinates, connectivity_matrix, charges) """ # Take out elements, coordinates and connectivity matrix elements = [atom.GetSymbol() for atom in mol.GetAtoms()] charges = np.array([atom.GetFormalCharge() for atom in mol.GetAtoms()]) conformer_coordinates = [] for conformer in mol.GetConformers(): coordinates = conformer.GetPositions() conformer_coordinates.append(coordinates) conformer_coordinates = np.array(conformer_coordinates) connectivity_matrix = Chem.GetAdjacencyMatrix(mol, useBO=True) return elements, conformer_coordinates, connectivity_matrix, charges
def cluster_by_rmsd(m: Chem.Mol, energies, rmsd_threshold: float): """ conformer in m should be assigned consecutive ids with delta=1 :param energies: :param m: :param rmsd_threshold: :return: """ rmsd_condensed = AllChem.GetConformerRMSMatrix(m) # rmsd_condensed = ConfGen.GetBestRMSMatrix(m) from rdkit.ML.Cluster.Butina import ClusterData clusters = ClusterData(rmsd_condensed, len(m.GetConformers()), distThresh=rmsd_threshold, isDistData=True) m_after_prune = Chem.Mol(m) m_after_prune.RemoveAllConformers() n_energies = [] for c in clusters: conf = m.GetConformer(c[0]) n_energies.append(energies[c[0]]) m_after_prune.AddConformer(conf, assignId=True) return m_after_prune, n_energies