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.
| Path | Content |
|---|---|
proteins/<UniProt>.json.gz | One protein: annotation, pockets, and one row per compound with its scores and the byte position of its top pose. |
compounds/<PVL>.json.gz | One compound: its catalogue entries and the proteins with the highest affinity; .all.json.gz has every protein. |
poses/<UniProt>.poses | Every pose of one protein (PVATLAS1): the top pose of each compound (SDF) and all modes of each pocket run (PDBQT). |
poses_redock/<UniProt>.poses | The same for the desalted forms of salt entries (rows whose pf column points to this file). |
structures/AF-<UniProt>-F1-model_v6.pdb | The AlphaFold model that was docked; also as .pdb.gz. |
tables/*.parquet | The bulk tables: pairs, pocket runs, modes, pockets, compounds (listed on Downloads). |
ligands/<PVL>.svg | The 2D drawing of a docked structure. |
MANIFEST.json | Every 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.jsonRead a pose file in Python
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 uses the standard library only: it 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 topChimeraX
open AF-P00533-F1-model_v6.pdb
open P00533_PVL01963_top.sdf
open P00533_PVL01963_pk1_modes.pdbqt
view #2py3Dmol 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"