Skip to main content

    Conformers & Minimization

    Embed conformers with ETKDGv3, minimize under MMFF94s or fall back to UFF, pick the lowest-energy conformer from stored energies, and write them to an SDF.

    Conformer generation lets you turn a flat SMILES into 3D structures ready for minimization, export, and downstream docking. The embedding parameters, force field choice (MMFF94s vs UFF), and how you pick the lowest-energy conformer are what most affect the quality of the geometry you carry forward.

    Generate conformers

    from rdkit import Chem
    from rdkit.Chem import AllChem
    
    mol = Chem.AddHs(Chem.MolFromSmiles("CCOC(=O)C1=CC=CC=C1"))
    params = AllChem.ETKDGv3()
    params.numThreads = 0  # use all cores
    ids = AllChem.EmbedMultipleConfs(mol, numConfs=10, params=params)
    print(f"Generated {len(ids)} conformers")

    Minimize

    props = AllChem.MMFFGetMoleculeProperties(mol)
    for cid in ids:
        AllChem.MMFFOptimizeMolecule(mol, confId=cid, mmffVariant="MMFF94s", nonBondedThresh=100.0, maxIters=200)
        energy = AllChem.MMFFGetMoleculeForceField(mol, props, confId=cid).CalcEnergy()
        mol.SetProp(f"energy_{cid}", f"{energy:.3f}")

    For neutral organics, MMFF94s is usually stable. For metals or unusual valence, fall back to UFF.

    Select the best conformer

    best = min(ids, key=lambda cid: float(mol.GetProp(f"energy_{cid}")))

    Export to SDF

    from rdkit.Chem import SDWriter
    
    writer = SDWriter("/workspace/outputs/conformers.sdf")
    for cid in ids:
        writer.write(mol, confId=cid)
    writer.close()

    Tips

    • Keep EmbedMultipleConfs deterministic by setting params.randomSeed.
    • Sanitize inputs first: Chem.SanitizeMol to catch valence issues early.
    • Store energies as props so downstream steps can filter without recomputing.

    Was this page helpful?

    On this page

    On this page

    Loading...