OK, seems ligands and PDBs are not really a trending topic here.... (or my posts are really poor).
Nevertheless the question is literally eating my brain so I went into a second direction: "the API" already skimmed here Help me in understanding the PDB file.
So inspecting and copying directly from the PDB entry 7RDX webpage the download value: https://models.rcsb.org/v1/7rdx/ligand?auth_seq_id=1005&label_asym_id=M&encoding=sdf&filename=7rdx_M_1N7.sdfI got this bit of code:
import requests
def main():
risposta = requests.get(f"https://models.rcsb.org/v1/7rdx/ligand?auth_seq_id=1005&label_asym_id=M&encoding=sdf",
allow_redirects=True)
open(filename, 'wb').write(risposta.content)
print(risposta.status_code)
if __name__ == '__main__':
filename = '7rdx_M_1N7.sdf'
main()
That is equivalent to feeding this:
{
"atom_site": [
{
"auth_seq_id": 1005,
"label_asym_id": "M"
}
]
}
to the 'https://models.rcsb.org/#/General/ligand-post' test webpage Request body.
now need to figure out how to get the auth_seq_id
and the label_asym_id
parameters for all the
'non_polymer_entity_ids' of my targed PDB 7RDX from the https://data.rcsb.org/rest/v1/ DATA API.
Went till here:
import requests
import json
def main(entry_id: str):
risposta = requests.get(f"https://data.rcsb.org/rest/v1/core/entry/{entry_id}/")
parsed = json.loads(risposta.content.decode())
print(risposta.status_code)
print((parsed))
print(parsed["rcsb_entry_container_identifiers"]["non_polymer_entity_ids"])
print('\n', type(parsed))
parsed_lig = parsed["rcsb_entry_container_identifiers"]["non_polymer_entity_ids"]
print('\n\n',parsed_lig, type(parsed_lig))
if __name__ == '__main__':
main('7rdx')
output :
['7', '8', '9', '10', '11'] <class 'list'>
The list values are the ids of the 'non_polymer_entity_ids' of my targed PDB 7RDX.
Right now I am trying to recover the the auth_seq_id
and the label_asym_id
for every instance of the 'non_polymer_entity_ids' inside my mmCIF/PDBx using the DATA API.
Not sure this is the fastest and right way using the RCSB PDB API to accomplish the OP question (download all ligands of the model structure (not the ligands models)) from the PDB database. Please feel free to add more or point me towards the best solution.
EDITED:
It took a while, I am sure this is not the right way to make good use of all the databases, there should be a way to navigate the API schemas better and faster, and to get and manage the intermediate values needed to get the two keys for the download from ModelServer "Post /v1/{id}/ligand Coordinates of the first group satisfying the given criteria", anyway:
import requests
import json
parsed_lig_dict = {}
def main(entry_id: str):
risposta = requests.get(f"https://data.rcsb.org/rest/v1/core/entry/{entry_id}/")
parsed = json.loads(risposta.content.decode())
# print(risposta.status_code)
# print((parsed))
# print(parsed["rcsb_entry_container_identifiers"]["non_polymer_entity_ids"])
# print('\n', type(parsed))
parsed_lig = parsed["rcsb_entry_container_identifiers"]["non_polymer_entity_ids"]
# print('\n\n',parsed_lig, type(parsed_lig))
# for i in parsed:
# print('\n', i , parsed[i])
for lig in parsed_lig:
risposta = requests.get(f"https://data.rcsb.org/rest/v1/core/nonpolymer_entity/{entry_id}/{lig}")
parsed = json.loads(risposta.content.decode())
# print('\n',risposta.status_code, risposta.content)
# print(parsed["rcsb_nonpolymer_entity_container_identifiers"]["asym_ids"],
# parsed["pdbx_entity_nonpoly"]["comp_id"])
parsed_lig_dict[lig] = [parsed["pdbx_entity_nonpoly"]["comp_id"] ,
dict.fromkeys(parsed["rcsb_nonpolymer_entity_container_identifiers"]["asym_ids"])]
for lig in parsed_lig_dict:
for chain in parsed_lig_dict[lig][1]:
risposta = requests.get(f"https://data.rcsb.org/rest/v1/core/nonpolymer_entity_instance/{entry_id}/{chain}")
# print(risposta.status_code)
parsed = json.loads(risposta.content.decode())
# print('\n',risposta.status_code, risposta.content)
# print(chain , '--> ',parsed["rcsb_nonpolymer_entity_instance_container_identifiers"]["auth_seq_id"])
parsed_lig_dict[lig][1][chain] = parsed["rcsb_nonpolymer_entity_instance_container_identifiers"]["auth_seq_id"]
# print(parsed_lig_dict)
# for i in parsed_lig_dict:
# print(parsed_lig_dict[i])
# for i in parsed_lig_dict:
# for y in parsed_lig_dict[i][1]:
# print(i,parsed_lig_dict[i][0], y , parsed_lig_dict[i][1][y])
cnt = 1
for i in parsed_lig_dict:
for y in parsed_lig_dict[i][1]:
seq_id = parsed_lig_dict[i][1][y]
chain = y
comp_id = parsed_lig_dict[i][0]
print(seq_id , y)
risposta = requests.get(f"https://models.rcsb.org/v1/7rdx/ligand?auth_seq_id={seq_id}&label_asym_id={chain}&encoding=sdf" ,
allow_redirects=True)
print(risposta.status_code)
filename = f"lig_{comp_id}_{chain}_{seq_id}_{cnt}.sdf"
open(filename, 'wb').write(risposta.content)
cnt += 1
if __name__ == '__main__':
main('7rdx')
This approach is very slow on my machine, the other two answers that parse the downloaded full mmCIF file via Biopython Structure Object are faster even adding the translation .sdf
files to SMILES via Openbabel. I think this is because I translate the DATA API JSON formatted schema into a dictionary to extract the data I need, there should be another way to make use of that data. This way doesn't need installed Biopython though.