Skip to content

Docking

Dock ligands to a Protein with the Deep Origin docking tool.

Prerequisites

Docking a single Ligand

Use Docking with your protein, pocket, and ligand. Here pocket is a Pocket from PocketFinder . Both Docking.run() and Docking.start() use client.executions.create: run() sets sync=True for one ligand (one blocking request until completion), and start() sets sync=False for a single persisted async job with two or more ligands. Docking.run() returns a LigandSet of poses.

from deeporigin.drug_discovery import Docking

docking = Docking(protein=protein, pocket=pocket, ligand=ligand)
poses = docking.run()

Estimating cost

To get a cost estimate without running the docking, call quote() on the Docking instance:

docking = Docking(protein=protein, pocket=pocket, ligand=ligand)
docking.quote()       # populates docking.estimate
docking.estimate      # estimated cost in dollars
docking.cost          # None until a billable run completes

After a completed run, the actual cost is on the same object:

docking = Docking(protein=protein, pocket=pocket, ligand=ligand)
poses = docking.run()

docking.cost  # actual cost in dollars

Viewing docked poses

Docked poses for that ligand can be viewed using:

protein.show(poses=poses)

You will see something similar to the following. Use the arrows to inspect individual poses.

Viewing pose scores and binding energy

Every pose is assigned a pose score and a binding energy. These can be viewed using:

poses

A widget similar to the following will be shown:

LigandSet with 15 poses

SMILES: Cc1[nH]c2cc(Cl)cc(Cl)c2c1CCN

Properties: Binding Energy, POSE SCORE, SMILES, initial_smiles

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

To work with a dataframe containing this data, use:

df = poses.to_dataframe()

Exporting poses to SDF

Poses can be saved to a SDF file using:

poses.to_sdf()

Docking many ligands

Using batch jobs

Tutorial

Follow the tutorial on how to dock ligands using batch jobs. This is best suited for large jobs with 100+ ligands.

Using functions

Several ligands in a LigandSet can be docked by passing ligands to Docking, then Docking.start() (async). Poll with sync() or Jupyter helpers until the job completes, then call get_results() to retrieve a LigandSet of poses.

docking = Docking(protein=protein, pocket=pocket, ligands=ligands)
docking.start()
# … wait for completion (docking.sync() in a loop, or watch() in notebooks) …
poses = docking.get_results()

poses is a LigandSet containing the docked poses. To work with a DataFrame:

df = poses.to_dataframe()

To filter poses to keep only top poses, use:

top_poses = poses.filter_top_poses()

These poses can be visualized as before:

protein.show(poses=poses)

If you need SDF files for the poses (e.g. for export), use get_poses() instead, which downloads the SDF files from the platform:

poses = docking.get_poses()
poses.to_sdf("my_poses.sdf")

To estimate the cost of docking a full LigandSet without running it:

docking = Docking(protein=protein, pocket=pocket, ligands=ligands)
docking.quote()
docking.estimate  # total estimated cost across all ligands

Working with existing runs

Reconnect to an asynchronous docking run started earlier, in this or a previous session, instead of re-submitting it:

# By execution id:
docking = Docking.from_id("<executionId>")

# Or the most recently created Docking run:
docking = Docking.from_last_run()

docking.sync()               # refresh status from the platform
poses = docking.get_results()

from_last_run() returns the newest execution of that tool type, so call it on the class you submitted with — ConstrainedDocking.from_last_run() for a constrained run.

Constrained docking

Use ConstrainedDocking to dock test ligands while preserving a reference binding mode. The platform derives harmonic constraints server-side from MCS alignment between each test ligand and a supplied reference pose. Callers provide reference_ligand (scaffold identity) and reference_pose (required 3D SDF coordinates); they do not pass constraint atom lists.

Dock-then-constrain pipeline

Dock a reference ligand, upload the best pose SDF, then constrained-dock analogs:

from deeporigin.drug_discovery import ConstrainedDocking, Docking

ref_poses = Docking(protein=protein, pocket=pocket, ligand=reference_ligand).run()
reference_pose = ref_poses.ligands[0]
reference_pose.sync(remote_path="testing/reference-pose.sdf")

cd = ConstrainedDocking(
    protein=protein,
    pocket=pocket,
    reference_ligand=reference_ligand,
    reference_pose=reference_pose,
    ligand=query_ligand,
)
poses = cd.run()

Each test ligand must have SMILES or a structure file on the platform (load from SDF/MOL2 and call ligand.sync(), or use Ligand.from_smiles and call ligand.sync()). The reference pose must have 3D coordinates.

SMILES-only test ligands

When a test ligand has no structure file, provide SMILES and sync the entity:

from deeporigin.drug_discovery import ConstrainedDocking, Ligand

test_ligand = Ligand.from_smiles("CC(C)O")
test_ligand.sync()

cd = ConstrainedDocking(
    protein=protein,
    pocket=pocket,
    reference_ligand=reference_ligand,
    reference_pose=reference_pose,
    ligand=test_ligand,
)
poses = cd.run()

The platform embeds the SMILES to an ephemeral 3D structure for MCS alignment. Reference ligand and reference pose still require structure files on the platform.

To view new poses together with the reference pose:

protein.show(poses=reference_pose + poses)

Inspect whether harmonic constraints were applied via the constrained property on each pose in poses.to_dataframe(). When MCS cannot match a test ligand, the tool free-docks that ligand and sets constrained=False.

Retrieve the reference pose echoed by the tool:

reported_reference = cd.get_reference_pose()

Multiple test ligands (async)

Pass ligands= and use start() / watch() for batch constrained docking:

cd = ConstrainedDocking(
    protein=protein,
    pocket=pocket,
    reference_ligand=reference_ligand,
    reference_pose=reference_pose,
    ligands=analogs,
)
cd.start()
# … wait for completion …
poses = cd.get_results()

MCS override

Force a common scaffold with mcs_smarts or mcs_smiles (mutually exclusive):

cd = ConstrainedDocking(
    protein=protein,
    pocket=pocket,
    reference_ligand=reference_ligand,
    reference_pose=reference_pose,
    ligand=query_ligand,
    mcs_smarts="C(=O)",
)
poses = cd.run()

Estimating cost

cd = ConstrainedDocking(
    protein=protein,
    pocket=pocket,
    reference_ligand=reference_ligand,
    reference_pose=reference_pose,
    ligand=query_ligand,
)
cd.run(quote=True)
cd.estimate

Filtering docking outputs

Filter docking results by score and related properties.

Deprecated: Complex

The examples below use the deprecated Complex type. New workflows should use Docking (and related APIs) instead of Complex.docking.

Here we assume that you have constructed a Complex object and successfully run Docking. Following convention, we assume that the Complex object is called sim.

Fetch docked poses

First, we get the results of Docking in a pandas DataFrame using:

poses = sim.docking.get_poses()
Inspecting the poses object shows us:

LigandSet with 2246 ligands

157 unique SMILES

Properties: Binding Energy, POSE SCORE, SCORE, SMILES, initial_smiles

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

Plot docking results

The metrics of all docked poses can be plotted in a scatter plot using:

poses.plot()

Pick top results

We can pick the top pose for each SMILES string using:

poses.filter_top_poses()