Skip to content
PocketVina Atlas

Download and visualise

How to take the data home, read one pose out of a pose file, and look at it in your own viewer. The example is Erlotinib (PVL01963) on EGFR (P00533).

What to download

Paths are relative to the data address https://bimsbstatic.mdc-berlin.de/akalin/asarigun/pocketvina_atlas/data/v1.1/. Single files of a protein or a pair are also on each protein page (Downloads), and a selection of pairs downloads as a ZIP from any table.

PathContent
proteins/<UniProt>.json.gzOne protein: annotation, pockets, and one row per compound with its scores and the byte position of its top pose.
compounds/<PVL>.json.gzOne compound: its catalogue entries and the proteins with the highest affinity; .all.json.gz has every protein.
poses/<UniProt>.posesEvery pose of one protein (PVATLAS1): the top pose of each compound (SDF) and all modes of each pocket run (PDBQT).
poses_redock/<UniProt>.posesThe same for the desalted forms of salt entries (rows whose pf column points to this file).
structures/AF-<UniProt>-F1-model_v6.pdbThe AlphaFold model that was docked; also as .pdb.gz.
tables/*.parquetThe bulk tables: pairs, pocket runs, modes, pockets, compounds (listed on Downloads).
ligands/<PVL>.svgThe 2D drawing of a docked structure.
MANIFEST.jsonEvery file of the release with its size and SHA-256.

Download with curl or wget

The server answers range requests, so one pose can be fetched without the whole pose file: each row of the protein's table gives the byte offset and length of its top pose (top_off, top_len), and each record is one gzip member.

BASE=https://bimsbstatic.mdc-berlin.de/akalin/asarigun/pocketvina_atlas/data/v1.1

# the protein's table: one row per compound (column names in the file)
curl -s $BASE/proteins/P00533.json.gz | gunzip > P00533.json

# the AlphaFold model that was docked
curl -O $BASE/structures/AF-P00533-F1-model_v6.pdb

# every pose of the protein in one file (large)
wget $BASE/poses/P00533.poses

# one pose only: a range request with the row's top_off and top_len (Erlotinib on EGFR)
curl -s -r 1568949-1569842 $BASE/poses/P00533.poses | gunzip > P00533_PVL01963_top.sdf

# a bulk table, and the list of every file with its checksum
curl -O $BASE/tables/pairs_by_protein.parquet
curl -O $BASE/MANIFEST.json

The easy way: the Python package

The PocketVina Python package reads this Atlas directly, with no GPU needed. You can search the results, rank them, view a pair's poses, save them and download part of the Atlas for offline use. Each step below shows what it prints in a console, with long names cut short to fit; in Jupyter or Colab the same results come as HTML tables. The example is imatinib on ABL1.

pip install "pocketvina>=0.3.1"

Open the Atlas

It reads this website's data over the internet and keeps what it has read for the next time.

from pocketvina import Atlas

atlas = Atlas()
atlas
Output
PocketVina Atlas v1.1: 18,713 proteins, 2,559 drugs, 48,406,051 pairs [https://bimsbstatic.mdc-berlin.de/akalin/asarigun/pocketvina_atlas/data/v1.1/]

Find a protein or a drug

search takes a name or any identifier, closest match first.

atlas.search("ABL1")
Output
      kind      id                     name       matched                    value
0  protein  P00519  ABL1: Tyrosine-prote...          gene                     ABL1
1  protein  Q8TDN4  CABLES1: CDK5 and AB...  protein name  CDK5 and ABL1 enzyme...
2  protein  Q9BTV7  CABLES2: CDK5 and AB...  protein name  CDK5 and ABL1 enzyme...

protein and drug show what the Atlas knows about one of them.

atlas.protein("ABL1")
Output
ProteinInfo P00519 (ABL1): Tyrosine-protein kinase ABL1  AlphaFold model AF-P00519-F1-model_v6, mean pLDDT 63.4  class Enzyme > Kinase  5 pockets (P2Rank)  10 associated diseases (Open Targets)
atlas.drug("imatinib")
Output
DrugInfo PVL00129: Imatinib (STI571)  ChEMBL ID: CHEMBL1642  catalogue numbers: S1026, S2475  InChIKey: KTUFNOKKBVMGRW-UHFFFAOYSA-N  parent SMILES: Cc1ccc(NC(=O)c2ccc(CN3CCN(C)CC3)cc2)cc1Nc1nccc(-c2cccnc2)n1  library SMILES: CN1CCN(CC1)CC2=CC=C(C=C2)C(=O)NC3=CC=C(C)C(=C3)NC4=NC=CC(=N4)C5=CC=CN=C5.C[S](O)(=O)=O  docked SMILES: Cc1ccc(NC(=O)c2ccc(CN3CCN(C)CC3)cc2)cc1Nc1nccc(-c2cccnc2)n1  synonyms: Glamox, Imatinib  ATC: L01EA01

Rank the results

The drugs with the highest affinity on a protein, and the proteins a drug binds most strongly, lowest Vina score first.

atlas.best_scores(protein="ABL1", top=5)
Output
  protein_id  gene ligand_id                  name  vina  best_pocket  best_mode  ligand_efficiency
0     P00519  ABL1  PVL00898             Hypericin -13.4            1          1              0.353
1     P00519  ABL1  PVL01982  Midostaurin (PKC412) -11.4            1          1              0.265
2     P00519  ABL1  PVL00250          Drospirenone -11.0            1          1              0.407
3     P00519  ABL1  PVL02025          Sanguinarine -10.8            1          1              0.432
4     P00519  ABL1  PVL00271         Staurosporine -10.7            1          1              0.306
atlas.best_scores(ligand="imatinib", top=5)
Output
  protein_id    gene ligand_id               name  vina  best_pocket  best_mode  ligand_efficiency
0     Q9H9P8  L2HGDH  PVL00129  Imatinib (STI571) -12.0            1          1              0.324
1     Q9BZH6   WDR11  PVL00129  Imatinib (STI571) -11.9            1          1              0.322
2     Q7KZN9   COX15  PVL00129  Imatinib (STI571) -11.7            1          1              0.316
3     Q8WZ60   KLHL6  PVL00129  Imatinib (STI571) -11.7            1          1              0.316
4     O75908   SOAT2  PVL00129  Imatinib (STI571) -11.6            2          1              0.314

best_pocket and best_mode are the pocket and the mode of the pose with that Vina score.

One protein and one drug

select picks the poses of a pair; pocket="all" takes the highest-affinity pose in each pocket.

pair = atlas.select(protein="ABL1", ligand="imatinib", pocket="all")
pair
Output
Selection PV_P00519_PVL00129: protein P00519, ligand PVL00129, the highest-affinity pose in each pocket: 5 poses  SMILES: CN1CCN(CC1)CC2=CC=C(C=C2)C(=O)NC3=CC=C(C)C(=C3)NC4=NC=CC(=N4)C5=CC=CN=C5.C[S](O)(=O)=O  pocket  lowest Vina score (kcal/mol)  modes
     1 *                          -8.5  1
     2                            -6.9  1
     3                            -7.8  1
     4                            -7.7  1
     5                            -6.8  1

The star in that list marks the pocket of the pair's highest-affinity pose.

show draws the pair in 3D, the same view as on a protein page here: in Jupyter, Colab or VS Code below the cell, in a script as an HTML file whose path it returns. Below is the page it draws for this pair, and it works the same way: rotate the protein, switch pockets or step through the poses.

pair.show()
Output

bust gives the PoseBusters checks of those poses, one row per pose: pb_valid is true when a pose passes them all, and pb_status is valid, invalid or the reason a pose was not checked.

checks = pair.bust()
checks[["pocket", "mode", "vina", "pb_valid", "pb_status"]]
Output
   pocket  mode  vina  pb_valid pb_status
0       1     1  -8.5      True     valid
1       2     1  -6.9      True     valid
2       3     1  -7.8      True     valid
3       4     1  -7.7      True     valid
4       5     1  -6.8      True     valid

pair.export() writes the poses as an SDF file and returns its path; pair.export(protein=True) also writes the AlphaFold model as a PDB file.

pair.export()
Output
'/path/to/PV_P00519_PVL00129_pocketall_top.sdf'

Work offline

atlas.download(proteins=["ABL1"], out="my_atlas") copies what the Atlas has on those proteins into a folder, and Atlas("my_atlas") reads that folder without internet. The same commands work in a shell with pocketvina atlas.

The full guide, with every option: PocketVina Atlas in the PocketVina documentation. It also opens as a Colab notebook you can run in your browser.

Without the package: read a pose file yourself

Only if you would rather not install anything: this script reads the same poses out of a pose file with the Python standard library. The package above does this for you.

A pose file starts with a fixed header, then table A (offset and length of the top pose of each compound) and table B (the start of the mode block of each compound and pocket). The script below reads the protein's table, finds the compound's record (cidx, minus cidx_offset in the file of the desalted forms), and writes the top pose as SDF and the modes of its pocket as PDBQT. For a downloaded file, read the same byte ranges from disk.

import gzip, json, struct, sys, urllib.request

BASE = sys.argv[1] if len(sys.argv) > 1 else "https://bimsbstatic.mdc-berlin.de/akalin/asarigun/pocketvina_atlas/data/v1.1"
UNIPROT, PVL = "P00533", "PVL01963"                      # EGFR, erlotinib
HEADER = struct.Struct("<8sIIIIQQQQQQII")                # PVATLAS1 header (first 88 of 128 bytes)

def get(path, start=None, end=None):                     # a whole file, or bytes start..end (inclusive)
    req = urllib.request.Request(f"{BASE}/{path}", headers={} if start is None else {"Range": f"bytes={start}-{end}"})
    with urllib.request.urlopen(req) as r:
        return r.read()

protein = json.loads(gzip.decompress(get(f"proteins/{UNIPROT}.json.gz")))
c = {name: i for i, name in enumerate(protein["columns"])}
row = next(r for r in protein["rows"] if r[c["pvl"]] == PVL)
pose_file = protein["poses_redock" if row[c["pf"]] == 1 else "poses"]    # pf 1: the file of the desalted forms
path = pose_file["file"]

magic, version, N, K, _, table_a, table_b, *_ = HEADER.unpack(get(path, 0, HEADER.size - 1))
assert magic == b"PVATLAS1"
i = row[c["cidx"]] - pose_file.get("cidx_offset", 0)     # the compound's record in this file
off, length = struct.unpack("<QI", get(path, table_a + 12 * i, table_a + 12 * i + 11))   # table A: its top pose
assert (off, length) == (row[c["top_off"]], row[c["top_len"]])
open(f"{UNIPROT}_{PVL}_top.sdf", "wb").write(gzip.decompress(get(path, off, off + length - 1)))

pocket = row[c["pocket"]]                                 # table B: the modes of one pocket run
j = i * K + pocket - 1
start, end = struct.unpack("<2Q", get(path, table_b + 8 * j, table_b + 8 * j + 15))
if end > start:
    open(f"{UNIPROT}_{PVL}_pk{pocket}_modes.pdbqt", "wb").write(gzip.decompress(get(path, start, end - 1)))
print(f"{N} compounds, {K} pockets; top pose {length} bytes, pocket {pocket} modes {end - start} bytes")

Visualise locally

PyMOL

# in a shell
pymol AF-P00533-F1-model_v6.pdb P00533_PVL01963_top.sdf P00533_PVL01963_pk1_modes.pdbqt

# or at the PyMOL prompt
load AF-P00533-F1-model_v6.pdb
load P00533_PVL01963_top.sdf, top
load P00533_PVL01963_pk1_modes.pdbqt, modes
hide everything
show cartoon, AF-P00533-F1-model_v6
show sticks, top or modes
orient top

ChimeraX

open AF-P00533-F1-model_v6.pdb
open P00533_PVL01963_top.sdf
open P00533_PVL01963_pk1_modes.pdbqt
view #2

py3Dmol in Jupyter

import py3Dmol

view = py3Dmol.view(width=800, height=600)
view.addModel(open("AF-P00533-F1-model_v6.pdb").read(), "pdb")
view.setStyle({"model": 0}, {"cartoon": {"color": "lightgrey"}})
view.addModel(open("P00533_PVL01963_top.sdf").read(), "sdf")
view.setStyle({"model": 1}, {"stick": {"colorscheme": "yellowCarbon"}})
view.zoomTo({"model": 1})
view.show()

Mol* in the browser

Open the Mol* viewer and load the model and the pose files from your disk (Open Files). The 3D view on each protein page of this site is Mol* too.

Query the tables

DuckDB reads the Parquet tables over HTTP without downloading them: the ten compounds with the highest affinity on EGFR.

duckdb -c "
SELECT p.catalog_id, e.name, p.vina, p.best_pocket, p.best_mode, p.pb_status
FROM 'https://bimsbstatic.mdc-berlin.de/akalin/asarigun/pocketvina_atlas/data/v1.1/tables/pairs_by_protein.parquet' p
JOIN 'https://bimsbstatic.mdc-berlin.de/akalin/asarigun/pocketvina_atlas/data/v1.1/tables/compound_entries_annotated.parquet' e USING (catalog_id)
WHERE p.uniprot = 'P00533'
ORDER BY p.vina
LIMIT 10"

More on the files: Downloads and API.