3
$\begingroup$

I have thousands of PDB files and I need to extract the following information from each of them: an ID or the name of the small molecule (ligand) present in the complex.

Is there a way to do that with BioPython or similar tools? Taking this PDB entry as an example, the tools should return 7FM.

$\endgroup$
5
  • $\begingroup$ Can you please edit your question and include some examples and the output you would want from them? That way, we can test our solutions using your examples and we can be sure to give you the output you need. $\endgroup$
    – terdon
    Commented May 4, 2019 at 16:22
  • $\begingroup$ The PDB entry states that the ligand is 7FM. $\endgroup$
    – wrong_path
    Commented May 4, 2019 at 17:35
  • $\begingroup$ Anyway use the MMCIF2Dict tool to extract the information from the header via the PDB module of BioPython. If it's not in the header you can't do it because XML is not supported (not currently supported). Goodluck $\endgroup$
    – M__
    Commented May 4, 2019 at 17:43
  • $\begingroup$ And how do you use this function? $\endgroup$ Commented Oct 27, 2023 at 20:20
  • $\begingroup$ question is not clear anymore is the author referring to files a s PDB format or PDBx/mmcif format ? In case of the former Biopython can get the name of an HETATM residue see files.rcsb.org/view/5TO8.pdb $\endgroup$
    – pippo1980
    Commented Oct 27, 2023 at 20:34

3 Answers 3

3
$\begingroup$

I found out that the package PyPDB has the function get_ligands that does exactly what I'm looking for.

$\endgroup$
2
  • $\begingroup$ Thanks, for the feedback. Apologies for not spotting this. $\endgroup$
    – M__
    Commented May 7, 2019 at 9:44
  • 1
    $\begingroup$ No problem! Strange I was not able to find this tool before... $\endgroup$
    – wrong_path
    Commented May 7, 2019 at 11:52
1
$\begingroup$

copying from How to download ligands for PDB structure one of the answers, one of mines, code :


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/{pdb_file}/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__':  

   pdb_file = '5to8'   
       
   main(pdb_file)

output file : lig_7FM_B_701_1.sdf :

7FM
  ModelServer 0.9.10

 39 43  0  0  1  0  0  0  0  0  0
   -2.0610  -10.3590   40.5700 C   0  0  0  0  0  0  0  0  0  0  0  0
   -3.1170  -11.7950   42.6720 C   0  0  0  0  0  0  0  0  0  0  0  0
   -3.8640  -12.6100   43.6800 C   0  0  0  0  0  0  0  0  0  0  0  0
   -0.6970  -10.3290   36.5750 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.8210  -10.9080   35.9890 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.6600   -8.1940   35.9530 C   0  0  0  0  0  0  0  0  0  0  0  0
    2.0300   -9.0340   41.4650 N   0  0  0  0  0  0  0  0  0  0  0  0
    0.9390   -9.6680   41.0120 C   0  0  0  0  0  0  0  0  0  0  0  0
    0.7980  -10.0800   39.7250 N   0  0  0  0  0  0  0  0  0  0  0  0
    1.7720   -9.8430   38.8300 C   0  0  0  0  0  0  0  0  0  0  0  0
    2.9200   -9.1930   39.2330 C   0  0  0  0  0  0  0  0  0  0  0  0
    2.9910   -8.8020   40.5580 C   0  0  0  0  0  0  0  0  0  0  0  0
    4.0340   -8.8690   38.3150 C   0  0  0  0  0  0  0  0  0  0  0  0
   -0.0830   -9.8810   41.9510 N   0  0  0  0  0  0  0  0  0  0  0  0
   -1.3380  -10.4670   41.7760 C   0  0  0  0  0  0  0  0  0  0  0  0
   -3.3020  -10.9670   40.4240 C   0  0  0  0  0  0  0  0  0  0  0  0
   -3.8290  -11.6870   41.4760 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.8800  -11.1950   42.8370 C   0  0  0  0  0  0  0  0  0  0  0  0
   -5.0400  -12.4130   41.5840 N   0  0  0  0  0  0  0  0  0  0  0  0
   -5.2460  -12.6990   43.0180 C   0  0  0  0  0  0  0  0  0  0  0  0
    1.5160  -10.2930   37.5490 N   0  0  0  0  0  0  0  0  0  0  0  0
    0.4060  -11.1430   37.2090 C   0  0  0  0  0  0  0  0  0  0  0  0
   -2.8420  -10.2200   35.4050 N   0  0  0  0  0  0  0  0  0  0  0  0
   -2.7360   -8.8690   35.4000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -0.6240   -8.9330   36.5380 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.9670  -12.3410   35.9950 N   0  0  0  0  0  0  0  0  0  0  0  0
   -2.5680  -13.0870   37.1550 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.4690  -13.1930   34.5670 S   0  0  0  0  0  0  0  0  0  0  0  0
   -4.0440  -12.7310   37.3480 C   0  0  0  0  0  0  0  0  0  0  0  0
   -5.9670  -12.8650   40.6430 C   0  0  0  0  0  0  0  0  0  0  0  0
   -6.9720  -13.5050   40.9690 O   0  0  0  0  0  0  0  0  0  0  0  0
   -4.6200  -13.4130   38.5900 C   0  0  0  0  0  0  0  0  0  0  0  0
   -5.8010  -12.6200   39.1510 C   0  0  0  0  0  0  0  0  0  0  0  0
   -0.5520  -12.3690   33.7940 O   0  0  0  0  0  0  0  0  0  0  0  0
   -1.1430  -14.5640   34.8900 O   0  0  0  0  0  0  0  0  0  0  0  0
   -3.0530  -13.2140   33.7590 C   0  0  0  0  0  0  0  0  0  0  0  0
    5.0490   -8.1440   38.8710 F   0  0  0  0  0  0  0  0  0  0  0  0
    4.6120   -9.9430   37.7390 F   0  0  0  0  0  0  0  0  0  0  0  0
    3.5350   -8.1080   37.3100 F   0  0  0  0  0  0  0  0  0  0  0  0
  1 16  2  0  0  0  0
  1 15  1  0  0  0  0
  2 17  2  0  0  0  0
  2 18  1  0  0  0  0
  2  3  1  0  0  0  0
  3 20  1  0  0  0  0
  4  5  2  0  0  0  0
  4 25  1  0  0  0  0
  4 22  1  0  0  0  0
  5 23  1  0  0  0  0
  5 26  1  0  0  0  0
  6 24  1  0  0  0  0
  6 25  2  0  0  0  0
  7 12  2  0  0  0  0
  7  8  1  0  0  0  0
  8  9  2  0  0  0  0
  8 14  1  0  0  0  0
  9 10  1  0  0  0  0
 10 21  1  0  0  0  0
 10 11  2  0  0  0  0
 11 13  1  0  0  0  0
 11 12  1  0  0  0  0
 13 39  1  0  0  0  0
 13 38  1  0  0  0  0
 13 37  1  0  0  0  0
 14 15  1  0  0  0  0
 15 18  2  0  0  0  0
 16 17  1  0  0  0  0
 17 19  1  0  0  0  0
 19 30  1  0  0  0  0
 19 20  1  0  0  0  0
 21 22  1  0  0  0  0
 23 24  2  0  0  0  0
 26 28  1  0  0  0  0
 26 27  1  0  0  0  0
 27 29  1  0  0  0  0
 28 36  1  0  0  0  0
 28 34  2  0  0  0  0
 28 35  2  0  0  0  0
 29 32  1  0  0  0  0
 30 33  1  0  0  0  0
 30 31  2  0  0  0  0
 32 33  1  0  0  0  0
M  END
> <model_server_result.job_id>
RFDalM1AmREvgkv0PqdfQw

> <model_server_result.datetime_utc>
2023-10-27 22:13:14

> <model_server_result.server_version>
0.9.10

> <model_server_result.query_name>
ligand

> <model_server_result.source_id>
pdb-bcif

> <model_server_result.entry_id>
5to8

> <model_server_params.name>
atom_site

> <model_server_params.value>
{"label_asym_id":"B","auth_seq_id":701}

> <model_server_stats.io_time_ms>
5

> <model_server_stats.parse_time_ms>
76

> <model_server_stats.create_model_time_ms>
2

> <model_server_stats.query_time_ms>
244

> <model_server_stats.encode_time_ms>
0

> <model_server_stats.element_count>
39

$$$$

picture of .sdf file :

enter image description here

$\endgroup$
0
$\begingroup$

my attempt, will get only non water (H2O) or non aa (aminoacid) present in the PDB .... tricky if the ligand is an aa :

from Bio.PDB import PDBParser

from Bio.PDB import Selection

d = {'CYS': 'C', 'ASP': 'D', 'SER': 'S', 'GLN': 'Q', 'LYS': 'K',
     'ILE': 'I', 'PRO': 'P', 'THR': 'T', 'PHE': 'F', 'ASN': 'N', 
     'GLY': 'G', 'HIS': 'H', 'LEU': 'L', 'ARG': 'R', 'TRP': 'W', 
     'ALA': 'A', 'VAL':'V', 'GLU': 'E', 'TYR': 'Y', 'MET': 'M'}

pdb_file = '5to8'

struct = PDBParser(QUIET = True).get_structure(pdb_file, pdb_file+'.pdb')

res_list = Selection.unfold_entities(struct , 'R')

for i in res_list :
    
    if i.resname != 'HOH' and i.resname not in d :
    
        print(i, i.resname)

output :

<Residue 7FM het=H_7FM resseq=701 icode= > 7FM
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.