Exemplo n.º 1
0
    def _generate_conformers(self, n_confs=None):
        """
        Use a simulated annealing approach to generate conformers for this
        molecule.

        Keyword Arguments:
            n_confs (int): Number of conformers requested if None default to
            autode.Config.num_conformers
        """

        n_confs = n_confs if n_confs is not None else Config.num_conformers
        self.conformers = []

        if self.smiles is not None and self.rdkit_conf_gen_is_fine:
            logger.info(f'Using RDKit to gen conformers. {n_confs} requested')

            method = AllChem.ETKDGv2()
            method.pruneRmsThresh = Config.rmsd_threshold
            method.numThreads = Config.n_cores

            logger.info(
                'Running conformation generation with RDKit... running')
            conf_ids = list(
                AllChem.EmbedMultipleConfs(self.rdkit_mol_obj,
                                           numConfs=n_confs,
                                           params=method))
            logger.info('                                          ... done')

            conf_atoms_list = [
                atoms_from_rdkit_mol(self.rdkit_mol_obj, conf_id)
                for conf_id in conf_ids
            ]

            methods.add('ETKDGv2 algorithm (10.1021/acs.jcim.5b00654) '
                        f'implemented in RDKit v. {rdkit.__version__}')

        else:
            logger.info('Using repulsion+relaxed (RR) to generate conformers')
            with Pool(processes=Config.n_cores) as pool:
                results = [
                    pool.apply_async(get_simanl_atoms, (self, None, i))
                    for i in range(n_confs)
                ]
                conf_atoms_list = [res.get(timeout=None) for res in results]

            methods.add('RR algorithm (???) implemented in autodE')

        # Add the unique conformers
        for i, atoms in enumerate(conf_atoms_list):
            conf = get_conformer(name=f'{self.name}_conf{i}', species=self)
            conf.set_atoms(atoms)

            # If the conformer is unique on an RMSD threshold
            if conf_is_unique_rmsd(conf, self.conformers):
                self.conformers.append(conf)

        logger.info(f'Generated {len(self.conformers)} unique conformer(s)')
        return None
Exemplo n.º 2
0
def init_organic_smiles(molecule, smiles):
    """
    Initialise a molecule from a SMILES string, set the charge, multiplicity (
    if it's not already specified) and the 3D geometry using RDKit

    Arguments:
        molecule (autode.molecule.Molecule):
        smiles (str): SMILES string
    """

    try:
        molecule.rdkit_mol_obj = Chem.MolFromSmiles(smiles)

        if molecule.rdkit_mol_obj is None:
            logger.warning('RDKit failed to initialise a molecule')
            return init_smiles(molecule, smiles)

        molecule.rdkit_mol_obj = Chem.AddHs(molecule.rdkit_mol_obj)
    except RuntimeError:
        raise RDKitFailed

    molecule.charge = Chem.GetFormalCharge(molecule.rdkit_mol_obj)
    molecule.mult = calc_multiplicity(molecule,
                                      NumRadicalElectrons(molecule.rdkit_mol_obj))
    bonds = [(bond.GetBeginAtomIdx(), bond.GetEndAtomIdx())
             for bond in molecule.rdkit_mol_obj.GetBonds()]

    # Generate a single 3D structure using RDKit's ETKDG conformer generation
    # algorithm
    method = AllChem.ETKDGv2()
    method.randomSeed = 0xf00d
    AllChem.EmbedMultipleConfs(molecule.rdkit_mol_obj, numConfs=1, params=method)
    molecule.atoms = atoms_from_rdkit_mol(molecule.rdkit_mol_obj, conf_id=0)
    make_graph(molecule, bond_list=bonds)

    # Revert back to RR if RDKit fails to return a sensible geometry
    if not are_coords_reasonable(coords=molecule.coordinates):
        molecule.rdkit_conf_gen_is_fine = False
        molecule.atoms = get_simanl_atoms(molecule, save_xyz=False)

    for atom, _ in Chem.FindMolChiralCenters(molecule.rdkit_mol_obj):
        molecule.graph.nodes[atom]['stereo'] = True

    for bond in molecule.rdkit_mol_obj.GetBonds():
        if bond.GetBondType() != Chem.rdchem.BondType.SINGLE:
            molecule.graph.edges[bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()]['pi'] = True
        if bond.GetStereo() != Chem.rdchem.BondStereo.STEREONONE:
            molecule.graph.nodes[bond.GetBeginAtomIdx()]['stereo'] = True
            molecule.graph.nodes[bond.GetEndAtomIdx()]['stereo'] = True

    check_bonds(molecule, bonds=molecule.rdkit_mol_obj.GetBonds())

    return None
Exemplo n.º 3
0
def test_rdkit_atoms():

    mol = Chem.MolFromSmiles('C')
    mol = Chem.AddHs(mol)

    AllChem.EmbedMultipleConfs(mol, numConfs=1)

    atoms = atoms_from_rdkit_mol(rdkit_mol_obj=mol, conf_id=0)
    assert len(atoms) == 5

    coords = np.array([atom.coord for atom in atoms])
    dist_mat = distance_matrix(coords, coords)

    # No distance between the same atom
    assert dist_mat[0, 0] == 0.0

    # CH bond should be ~1 Å
    assert 0.9 < dist_mat[0, 1] < 1.2