In [1]:
from dotenv import load_dotenv
load_dotenv()
Out[1]:
True
In [2]:
%load_ext autoreload
%autoreload 2

Docking a single ligand¶

This notebook shows you how to dock a single ligand to a protein.

Setup¶

First, we'll import the necessary Deep Origin drug discovery modules.

In [3]:
from deeporigin.drug_discovery import (
    BRD_DATA_DIR,
    Pocket,
    Protein,
    Protonation,
    Docking,
    Ligand,
    LigandSet,
)

from deeporigin.platform import DeepOriginClient

You don't have to explictitly initialize a client, but you can if you want:

In [4]:
client = DeepOriginClient()
client
/home/runner/work/do-dd-client/do-dd-client/.venv/lib/python3.11/site-packages/jwt/api_jwt.py:147: InsecureKeyLengthWarning: The HMAC key is 6 bytes long, which is below the minimum recommended length of 32 bytes for SHA256. See RFC 7518 Section 3.2.
  return self._jws.encode(
Out[4]:
DeepOrigin Platform Client for Local User (org_key=deeporigin, base_url=http://127.0.0.1:4931/)

Load protein and register on the platform¶

We use the the same BRD protein as in our other notebooks, and use the sync method to upload the PDB file and register it with the data platform:

In [5]:
protein = Protein.from_file(BRD_DATA_DIR / "brd.pdb")
protein.remove_water()
protein.sync()
protein.id
Out[5]:
'brd'

Load ligand¶

We load a ligand from a SDF file on disk. You can also import a ligand from a SMILES string, etc. Once again, we use the sync method to upload the file (if any) and register with the data platform.

In [6]:
ligand = Ligand.from_sdf(BRD_DATA_DIR/"brd-2.sdf")
ligand.sync()
ligand
<rdkit.Chem.rdchem.Mol object at 0x7fda400a6b20>
Out[6]:
In [7]:
ligand.id
Out[7]:
'brd-2'

Protonate Ligand¶

We use the protonation tool to protonate the ligand and use the most probable species at that pH to dock. Note that the Protonator tool can modify our ligand.

In [8]:
protonator = Protonation(ligand=ligand)
protonator.run()
Out[8]:

LigandSet with 1 ligand

SMILES: CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1 PROTONATED (pH=7.4) 2D

Properties: initial_smiles, r_exp_dg

Use .to_dataframe() to convert to a dataframe, .show_df() to view dataframewith structures, or .show() for 3D visualization, .prepare() to prepare ligands for docking

Work with a pocket¶

Here, we will use a previously identified novel pocket using the PocketFinder tool.

In [9]:
pockets = Pocket.from_result(protein_id=protein.id)
pocket = pockets[0]
pocket
Out[9]:
Pocket:
╭─────────────────────────┬──────────────────────────────────────╮
│ Name                    │ pocket_1                             │
├─────────────────────────┼──────────────────────────────────────┤
│ ID                      │ c002d6b3-0d66-4265-91db-8bec0392751d │
├─────────────────────────┼──────────────────────────────────────┤
│ Protein ID              │ brd                                  │
├─────────────────────────┼──────────────────────────────────────┤
│ Color                   │ red                                  │
├─────────────────────────┼──────────────────────────────────────┤
│ Center                  │ (-13.52, -4.94, 15.46)               │
├─────────────────────────┼──────────────────────────────────────┤
│ Box size                │ 14.00 × 14.00 × 19.00 Å              │
├─────────────────────────┼──────────────────────────────────────┤
│ Volume                  │ 300 ų                               │
├─────────────────────────┼──────────────────────────────────────┤
│ Total SASA              │ 1225.8883 Ų                         │
├─────────────────────────┼──────────────────────────────────────┤
│ Polar SASA              │ 309.8629 Ų                          │
├─────────────────────────┼──────────────────────────────────────┤
│ Polar/Apolar SASA ratio │ 0.3382689                            │
├─────────────────────────┼──────────────────────────────────────┤
│ Hydrophobicity          │ 29.92                                │
├─────────────────────────┼──────────────────────────────────────┤
│ Polarity                │ 10                                   │
├─────────────────────────┼──────────────────────────────────────┤
│ Drugability score       │ 0.94304204                           │
├─────────────────────────┼──────────────────────────────────────┤
│ Pocket count            │ 1                                    │
├─────────────────────────┼──────────────────────────────────────┤
│ Pocket min size         │ 30 ų                                │
╰─────────────────────────┴──────────────────────────────────────╯

Show pocket¶

Here, we view the pocket in the protein:

In [10]:
protein.show(pockets=[pocket])

Show docking box¶

We can also view the docking box that is constructed from this pokcet:

In [11]:
docking = Docking(protein=protein, pocket=pockets[0], ligand=ligand)
docking.show_box()

Estimate cost¶

Before running any tool, we can estimate the cost by passing quote=True as follows:

In [12]:
docking.run(quote=True)
docking.estimate
Out[12]:
0.2

Dock ligand¶

We can now run the docking tool. Because we're docking a single ligand, we get back poses immediately. Docking.run (like all run methods) is a blocking synchronouse operation.

In [13]:
poses = docking.run()

We can view all poses in a dataframe:

In [14]:
poses.to_dataframe()
Out[14]:
id box_size_z best_pose box_size_y pocket_center binding_energy box_size_x pose_score protein_id pocket_id SMILES
0 brd-2 20 True 20 [-13.146394729614258, -5.712231636047363, 14.7... -8.015328 20 0.904670 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
1 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -8.961081 20 0.898408 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
2 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -7.692511 20 0.852781 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
3 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -9.012382 20 0.807688 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
4 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -7.441937 20 0.796831 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
5 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -8.609729 20 0.757949 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
6 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -8.411566 20 0.709940 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
7 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -7.697807 20 0.624421 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
8 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -7.191995 20 0.594424 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
9 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -6.837277 20 0.585849 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
10 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -6.739297 20 0.573230 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
11 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -8.172841 20 0.544384 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
12 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -7.280019 20 0.537316 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
13 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -8.083034 20 0.535973 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
14 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -7.644990 20 0.534965 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1
15 brd-2 20 False 20 [-13.146394729614258, -5.712231636047363, 14.7... -8.500072 20 0.513628 brd pocket-test-id CN(C)C(=O)c1cccc(-c2cn(C)c(=O)c3[nH]ccc23)c1

Show poses¶

To visualize the poses, we download them and show them in the protein:

In [15]:
poses.download()
protein.show(poses=poses)
Downloading files:   0%|          | 0/16 [00:00<?, ?file/s]
Downloading files: 100%|██████████| 16/16 [00:00<00:00, 198.16file/s]