---
name: rdkit
description: >
  Use RDKit for molecular conformer generation, SMILES/InChI handling, molecular
  descriptors, fingerprints, and substructure searching. Python-based toolkit.
compatibility: >
  Requires RDKit Python package (conda install -c conda-forge rdkit or pip install rdkit).
catalog-hidden: true
---

# RDKit — Conformers and Molecular Representations

## When to Use

- User needs to generate multiple 3D conformers for a molecule
- User wants to compute molecular fingerprints or descriptors
- User needs SMILES canonicalization or InChI generation
- User wants substructure matching or molecular similarity
- User needs to embed a molecule and optimize geometry with MMFF94/UFF

## Prerequisites

1. RDKit installed (`python -c "from rdkit import Chem; print(Chem.__version__)"`)

## Workflow Steps

### Conformer Generation

```
catgo_workflow_engine(action="add_task", params={
  "workflow_id": "wf_xxx",
  "task_type": "shell",
  "name": "rdkit_conf",
  "command": "python gen_conformers.py",
  "input_files": {
    "gen_conformers.py": "<script content>"
  },
  "system_name": "caffeine_conformers"
})
```

## Script — Conformer Generation

```python
from rdkit import Chem
from rdkit.Chem import AllChem, rdMolDescriptors

smiles = "CN1C=NC2=C1C(=O)N(C(=O)N2C)C"  # caffeine
mol = Chem.MolFromSmiles(smiles)
mol = Chem.AddHs(mol)

# Generate conformers
params = AllChem.ETKDGv3()
params.numThreads = 0  # use all cores
params.pruneRmsThresh = 0.5  # Angstrom RMSD pruning

cids = AllChem.EmbedMultipleConfs(mol, numConfs=50, params=params)
print(f"Generated {len(cids)} conformers")

# Optimize with MMFF94
results = AllChem.MMFFOptimizeMoleculeConfs(mol, numThreads=0)

# Sort by energy and write
energies = [(cid, res[1]) for cid, res in zip(cids, results) if res[0] == 0]
energies.sort(key=lambda x: x[1])

writer = Chem.SDWriter("conformers.sdf")
for cid, energy in energies[:20]:  # top 20 lowest energy
    mol.SetProp("Energy_kcal/mol", f"{energy:.2f}")
    writer.write(mol, confId=cid)
writer.close()
```

## Script — Molecular Descriptors

```python
from rdkit import Chem
from rdkit.Chem import Descriptors, rdMolDescriptors

mol = Chem.MolFromSmiles("CCO")

print(f"MW:       {Descriptors.MolWt(mol):.2f}")
print(f"LogP:     {Descriptors.MolLogP(mol):.2f}")
print(f"HBD:      {rdMolDescriptors.CalcNumHBD(mol)}")
print(f"HBA:      {rdMolDescriptors.CalcNumHBA(mol)}")
print(f"TPSA:     {Descriptors.TPSA(mol):.2f}")
print(f"RotBonds: {Descriptors.NumRotatableBonds(mol)}")
```

## Script — Fingerprints and Similarity

```python
from rdkit import Chem, DataStructs
from rdkit.Chem import AllChem

mol1 = Chem.MolFromSmiles("c1ccccc1")  # benzene
mol2 = Chem.MolFromSmiles("c1ccncc1")  # pyridine

fp1 = AllChem.GetMorganFingerprintAsBitVect(mol1, radius=2, nBits=2048)
fp2 = AllChem.GetMorganFingerprintAsBitVect(mol2, radius=2, nBits=2048)

tanimoto = DataStructs.TanimotoSimilarity(fp1, fp2)
print(f"Tanimoto similarity: {tanimoto:.3f}")
```

## Script — SMILES to XYZ

```python
from rdkit import Chem
from rdkit.Chem import AllChem

mol = Chem.MolFromSmiles("CCO")
mol = Chem.AddHs(mol)
AllChem.EmbedMolecule(mol, AllChem.ETKDGv3())
AllChem.MMFFOptimizeMolecule(mol)

# Write XYZ
conf = mol.GetConformer()
symbols = [a.GetSymbol() for a in mol.GetAtoms()]
coords = conf.GetPositions()

with open("molecule.xyz", "w") as f:
    f.write(f"{len(symbols)}\n")
    f.write("Generated by RDKit\n")
    for sym, (x, y, z) in zip(symbols, coords):
        f.write(f"{sym} {x:.6f} {y:.6f} {z:.6f}\n")
```

## Parameter Guidance

| Parameter | Typical value | Notes |
|---|---|---|
| numConfs | 50-200 | More for flexible molecules |
| pruneRmsThresh | 0.5 Ang | Remove near-duplicate conformers |
| MMFF94 vs UFF | MMFF94 preferred | UFF as fallback for metals |
| Morgan radius | 2 | ECFP4 equivalent |
| nBits | 2048 | Fingerprint length |

## Common Pitfalls

1. **Forgetting AddHs** — RDKit molecules from SMILES have implicit H. Call `Chem.AddHs()` before 3D embedding.
2. **Embedding failure** — `EmbedMolecule` returns -1 on failure. Check return value; retry with `useRandomCoords=True`.
3. **MMFF94 unsupported atoms** — MMFF94 does not cover all elements. Use UFF for organometallics.
4. **Stereo loss** — ensure SMILES include stereochemistry (`/`, `\`, `@`, `@@`) if relevant.
5. **Large flexible molecules** — conformer generation for molecules with >10 rotatable bonds needs many conformers (200+).
6. **Sanitization errors** — invalid SMILES cause `MolFromSmiles` to return None. Always check for None.
