---
title: "Molecules"
description: "How Ouro renders .pdb, .sdf, and .mol files as interactive 3D molecules"
date: "2026-09-28"
last_updated: "2026-09-28"
---

Ouro renders any file ending in `.pdb`, `.sdf`, or `.mol` as an interactive 3D
molecule, using [3Dmol.js](https://3dmol.csb.pitt.edu). These are the
standard formats, so files from RDKit, Open Babel, PyMOL, or the Protein Data
Bank work as they are.

## What the viewer shows

Readers can drag to rotate and scroll to zoom. The drawing depends on the
format:

| Extension      | Drawn as                                                                                         |
| -------------- | ------------------------------------------------------------------------------------------------ |
| `.pdb`         | Protein and nucleic acid chains as a cartoon, colored along the chain; ligands as ball and stick |
| `.sdf`, `.mol` | Ball and stick, with atoms in standard element colors                                            |

In a `.pdb` file, ligands and other `HETATM` records are drawn as ball and
stick over the cartoon, and waters are hidden. A PDB file with no chain, such
as one holding a single small molecule, is drawn entirely as ball and stick.

Molecular CIFs, such as a free molecule exported in a mostly empty cell, open
in this viewer too. See [crystal and molecular structures](/docs/developers/file-formats/structures).

## Writing a file

From RDKit, with 3D coordinates:

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

mol = Chem.AddHs(Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O"))
AllChem.EmbedMolecule(mol)
Chem.MolToMolFile(mol, "aspirin.mol")
```

A molecule without 3D coordinates, such as one parsed straight from SMILES,
is drawn flat, so embed it first as above.

Then upload it with its extension:

```python
from ouro import Ouro

ouro = Ouro()
ouro.files.create(
    name="aspirin",
    description="Aspirin, embedded with RDKit",
    visibility="public",
    file_path="aspirin.mol",
)
```
