Answers.Body: <p>Here can use GraphiQL API provided by RCSB.
  Here is an example</p>
  <pre class="lang-py prettyprint-override"><code>import requests
  from rdkit import Chem
  pdbid = '7RDX'
  ls_smi = []
  
  query = f'''{{
    entry(entry_id: &quot;{pdbid}&quot;) {{
      nonpolymer_entities {{
        nonpolymer_comp {{
          rcsb_id
          pdbx_chem_comp_descriptor {{
            type
            comp_id
            program
            descriptor
          }}
        }}
      }}
    }}
  }}'''
  url = &quot;https://data.rcsb.org/graphql&quot;
  r = requests.post(url, json={'query': query})
  for i in r.json()['data']['entry']['nonpolymer_entities']:
      if i['nonpolymer_comp']['pdbx_chem_comp_descriptor'][0]['type'] == 'SMILES':
          ls_smi.append(Chem.CanonSmiles(i['nonpolymer_comp']['pdbx_chem_comp_descriptor'][0]['descriptor']))
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-09T22:49:42.360Z
Answers.Text: Thanks @AustinApple and welcome to the site. A good answer
Answers.UserDisplayName: M__
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-09T22:40:45.137Z
Answers.LastActivityDate: 2023-03-15T21:26:13.740Z
Answers.LastEditDate: 2023-03-15T21:26:13.740Z
Answers.UserDisplayName: AustinApple
Answers.Body: <p>OK, seems ligands and PDBs are not really a trending topic here.... (or my posts are really poor).</p>
  <p>Nevertheless the question is literally eating my brain so I went into a second direction: &quot;the API&quot; already skimmed here <a href="https://bioinformatics.stackexchange.com/questions/18076/help-me-in-understanding-the-pdb-file">Help me in understanding the PDB file</a>.</p>
  <p>So inspecting and copying directly from the PDB entry <a href="https://www.rcsb.org/structure/7RDX" rel="nofollow noreferrer">7RDX</a> webpage the download value: <a href="https://models.rcsb.org/v1/7rdx/ligand?auth_seq_id=1005&amp;label_asym_id=M&amp;encoding=sdf&amp;filename=7rdx_M_1N7.sdf" rel="nofollow noreferrer">https://models.rcsb.org/v1/7rdx/ligand?auth_seq_id=1005&amp;label_asym_id=M&amp;encoding=sdf&amp;filename=7rdx_M_1N7.sdf</a>I got this bit of code:</p>
  <pre><code>import requests
  
  
  def main():   
      risposta = requests.get(f&quot;https://models.rcsb.org/v1/7rdx/ligand?auth_seq_id=1005&amp;label_asym_id=M&amp;encoding=sdf&quot;,                      
                        allow_redirects=True)   
      open(filename, 'wb').write(risposta.content)
      print(risposta.status_code)
  
  if __name__ == '__main__':  
     filename = '7rdx_M_1N7.sdf'   
     main()
  </code></pre>
  <p>That is equivalent to feeding this:</p>
  <pre><code>{
    &quot;atom_site&quot;: [
      {
        &quot;auth_seq_id&quot;: 1005,
        &quot;label_asym_id&quot;: &quot;M&quot;
      }
    ]
  }
  </code></pre>
  <p>to the 'https://models.rcsb.org/#/General/ligand-post' test webpage Request body.</p>
  <p>now need to figure out how to get the <code>auth_seq_id</code> and the <code>label_asym_id </code> parameters for all the
  'non_polymer_entity_ids' of my targed PDB 7RDX from the <a href="https://data.rcsb.org/rest/v1/" rel="nofollow noreferrer">https://data.rcsb.org/rest/v1/</a> DATA API.</p>
  <p>Went till here:</p>
  <pre><code>import requests
  import json
  
  def main(entry_id: str):
      risposta = requests.get(f&quot;https://data.rcsb.org/rest/v1/core/entry/{entry_id}/&quot;)   
      parsed = json.loads(risposta.content.decode())    
      print(risposta.status_code)    
      print((parsed))    
      print(parsed[&quot;rcsb_entry_container_identifiers&quot;][&quot;non_polymer_entity_ids&quot;])    
      print('\n', type(parsed))
      
      parsed_lig = parsed[&quot;rcsb_entry_container_identifiers&quot;][&quot;non_polymer_entity_ids&quot;]    
      print('\n\n',parsed_lig, type(parsed_lig))    
      
  
  if __name__ == '__main__':         
     main('7rdx')
  </code></pre>
  <p>output :</p>
  <pre><code> ['7', '8', '9', '10', '11'] &lt;class 'list'&gt;
  </code></pre>
  <p>The list values are the ids of the 'non_polymer_entity_ids' of my targed PDB 7RDX.</p>
  <p>Right now I am trying to recover the the <code>auth_seq_id</code> and the <code>label_asym_id </code> for every instance of the 'non_polymer_entity_ids' inside my mmCIF/PDBx using the DATA API.</p>
  <p>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.</p>
  <p><strong>EDITED:</strong></p>
  <p>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 &quot;Post /v1/{id}/ligand Coordinates of the first group satisfying the given criteria&quot;, anyway:</p>
  <pre><code>import requests
  import json
  
  parsed_lig_dict = {}
  
  def main(entry_id: str):    
      risposta = requests.get(f&quot;https://data.rcsb.org/rest/v1/core/entry/{entry_id}/&quot;)   
      parsed = json.loads(risposta.content.decode())    
      # print(risposta.status_code)    
      # print((parsed))    
      # print(parsed[&quot;rcsb_entry_container_identifiers&quot;][&quot;non_polymer_entity_ids&quot;])
      # print('\n', type(parsed))
      
      parsed_lig = parsed[&quot;rcsb_entry_container_identifiers&quot;][&quot;non_polymer_entity_ids&quot;]    
      # 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&quot;https://data.rcsb.org/rest/v1/core/nonpolymer_entity/{entry_id}/{lig}&quot;)    
          parsed = json.loads(risposta.content.decode())    
          # print('\n',risposta.status_code, risposta.content)        
          
          # print(parsed[&quot;rcsb_nonpolymer_entity_container_identifiers&quot;][&quot;asym_ids&quot;], 
                # parsed[&quot;pdbx_entity_nonpoly&quot;][&quot;comp_id&quot;])
                  
          parsed_lig_dict[lig] = [parsed[&quot;pdbx_entity_nonpoly&quot;][&quot;comp_id&quot;] , 
                                  dict.fromkeys(parsed[&quot;rcsb_nonpolymer_entity_container_identifiers&quot;][&quot;asym_ids&quot;])]
      
      for lig in parsed_lig_dict:        
          for chain in parsed_lig_dict[lig][1]:    
              risposta = requests.get(f&quot;https://data.rcsb.org/rest/v1/core/nonpolymer_entity_instance/{entry_id}/{chain}&quot;)        
              # print(risposta.status_code)
          
              parsed = json.loads(risposta.content.decode())        
              # print('\n',risposta.status_code, risposta.content)            
              # print(chain , '--&gt; ',parsed[&quot;rcsb_nonpolymer_entity_instance_container_identifiers&quot;][&quot;auth_seq_id&quot;])
              
              parsed_lig_dict[lig][1][chain] = parsed[&quot;rcsb_nonpolymer_entity_instance_container_identifiers&quot;][&quot;auth_seq_id&quot;]        
                 
      
      # 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&quot;https://models.rcsb.org/v1/7rdx/ligand?auth_seq_id={seq_id}&amp;label_asym_id={chain}&amp;encoding=sdf&quot; ,                              
                                allow_redirects=True)             
              print(risposta.status_code)
                          
              filename = f&quot;lig_{comp_id}_{chain}_{seq_id}_{cnt}.sdf&quot;            
              open(filename, 'wb').write(risposta.content)            
              cnt += 1
  
      
  if __name__ == '__main__':         
     main('7rdx')
  </code></pre>
  <p>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 <code>.sdf</code> 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.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-08T13:05:33.160Z
Answers.LastActivityDate: 2023-03-01T14:26:12.993Z
Answers.LastEditDate: 2023-03-01T14:26:12.993Z
Answers.UserDisplayName: pippo1980
Answers.Body: <p>Ok, cannot try the API approach, no resources during vacation. Got the download and parse/split approach, added conversion to SMILES by <strong>Openbabel</strong>. I believe it is exactly the same question of : <a href="https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb">https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb</a> from where I stole the juicy bit of the code:</p>
  <pre><code>## stealing from https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb
  
  from Bio import __version__
  
  
  print('BIOPYTHON Version : ' , __version__)
  
  from Bio.PDB import MMCIFParser, PDBIO, Select, PDBList
  
  import subprocess
  
  filename = '7rdx.cif'
  
  
  pdblist = PDBList()
  
  pdblist.retrieve_pdb_file(filename.upper().split('.')[0] , pdir = '.')
  
  
  pars = MMCIFParser(QUIET = True)
  
  struct = pars.get_structure('7rdx',  filename)
  
  
  print(struct, type(struct))
  
  
  def is_het(residue):
      res = residue.id[0]
      
      if res != &quot; &quot; and res != &quot;W&quot;:
          
          return True #1
  
      else:
      
          return False #0
   
  
  class ResidueSelect(Select):
      def __init__(self, chain, residue):
          self.chain = chain
          self.residue = residue
  
      def accept_chain(self, chain):
      
          if chain.id == self.chain.id:
              
              return True #1
          
          else:
              
              return False #0
          
          
      def accept_residue(self, residue):
          &quot;&quot;&quot; Recognition of heteroatoms - Remove water molecules &quot;&quot;&quot;
          
          if residue == self.residue and is_het(residue):
              
              return True #1
          
          else:
              
              return False #0
  
  
  for model in struct :
      
      
      dizio = model.child_dict
      
      print('\n'+ str(dizio))
      
      
  
  for model in struct:
      
      i = 1
      
      print(model, model.id)
      
      for chain in model:
          
          print(chain, chain.id)
          
          for res in chain:
              
              # print('\n'+'res : ', res, 'res.resname : ', res.resname)
              
              if res.id[0] != &quot; &quot; :
                  
                  
                  print('\n'+'res : ', res, res.id, res.resname)
                  
                  io = PDBIO()
                  
                  io.set_structure(struct)
                  
                  io.save(f&quot;lig_{chain.id}_{res.resname}_{i}.pdb&quot;, ResidueSelect(chain, res))
                  
                  try:
                      subprocess.run([&quot;openbabel.obabel&quot;, &quot;-ipdb&quot;, f&quot;lig_{chain.id}_{res.resname}_{i}.pdb&quot;, &quot;-osmi&quot; ,&quot;-O&quot;,
                                      
                                      f&quot;lig_{chain.id}_{res.resname}_{i}.smi&quot;])
                      
  
                      
                  except Exception as excp:
                      
                      print('\n ', excp, '\n')
                      
                      
                  
                  i += 1
  
  </code></pre>
  <p>Problem is Biopython parses <strong>mmCIF</strong>s files; that are now the official standard for RCSB PDB <a href="https://www.rcsb.org/news/feature/5c767ef5ea7d0653b99c876f" rel="nofollow noreferrer"><strong>Submission of PDBx/mmCIF format files for crystallographic depositions to the PDB will be mandatory from July 1st 2019 onward</strong>. PDB format files will no longer be accepted for deposition of structures solved by MX techniques.</a> A nice review about the long history of the 'new' format :[ <a href="https://www.sciencedirect.com/science/article/pii/S0022283622001796?via%3Dihub" rel="nofollow noreferrer">PDBx/mmCIF Ecosystem: Foundational Semantic Tools for Structural Biology</a>.</p>
  <p>Unfortunately the <code>Bio.PDB.MMCIFParser module</code> return a a structure that is:</p>
  <p><code>&lt;Structure id=7rdx&gt; &lt;class 'Bio.PDB.Structure.Structure'&gt;</code> so all the ligands are related to PDB chains classification and not PDBx entity.</p>
  <p>I could be wrong here, I am a novice in both Biopython and Structural Bioinformatics but this is what I've noticed, please feel free to elaborate on this and add a solution using the RCSB APIes ... before curiosity kills the cat</p>
  <p>PS:</p>
  <p><strong>NEEDs to be tested with sample containing water</strong></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-05T18:04:11.050Z
Answers.LastActivityDate: 2023-01-05T18:26:24.320Z
Answers.LastEditDate: 2023-01-05T18:26:24.320Z
Answers.UserDisplayName: pippo1980
Answers.Body: <p>adding a different way to solve the question , still without using RCSB PDB database, but using <code>Biopython.PDB.MMCIF2Dict</code> module to start to get a feeling on how info are stored in .cif format files. Ligands are selected amongs the ones in the structure for their Mw.</p>
  <p>Ligands are then saved using the same approach of first answer or a new one that takes advantage of <code>Biopython.PDB.Dice</code> module to extract and save portion of PDB. Again Openbabel is used to translate PDBs to SMILES.</p>
  <p>Code :</p>
  <pre><code>#!/usr/bin/env python3
  # -*- coding: utf-8 -*-
  &quot;&quot;&quot;
  Created on Thu Jan  5 11:43:07 2023
  
  @author: bob
  
  https://bioinformatics.stackexchange.com/questions/20301/how-to-download-ligands-for-pdb-structure?noredirect=1#comment29972_20301
  
  
  
  
  NEEDs to be tested with sample containing water
  
  
  &quot;&quot;&quot;
  
  ## stealing from https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb
  
  from Bio import __version__
  
  
  print('BIOPYTHON Version : ' , __version__)
  
  from Bio.PDB import (
                      MMCIFParser, 
                      PDBIO, 
                      Select, 
                      PDBList, 
                      MMCIF2Dict,
                      Dice
                      )
  
  import subprocess
  
  filename = '7rdx.cif'
  
  # filename = '7RDX.cif'  # this will  work , but biopython saves in lower case 
  
  
  # pdblist = PDBList()
  
  # pdblist.retrieve_pdb_file(filename.split('.')[0] , pdir = '.')
  
  
  pars = MMCIFParser(QUIET = True)
  
  struct = pars.get_structure('7rdx',  filename)
  
  
  # print(struct, type(struct))
  
  
  mmcifdict = MMCIF2Dict.MMCIF2Dict(filename)
  
  
  # print(mmcifdict)
  
  # for i in mmcifdict:
      
  #     print('\n', i ,'   ---&gt; ', mmcifdict[i])
      
  print('##############################################################')
      
  # print(mmcifdict['_entity'])
  
   
  print(mmcifdict['_pdbx_nonpoly_scheme.entity_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.asym_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.entity_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.mon_id'])
  
  ligands_map_mmcif = list(zip(mmcifdict['_pdbx_nonpoly_scheme.entity_id'],
                               
                               mmcifdict['_pdbx_nonpoly_scheme.asym_id'],
                               
                               mmcifdict['_pdbx_nonpoly_scheme.entity_id'],
                               
                               mmcifdict['_pdbx_nonpoly_scheme.mon_id']))
  
  
  print('#########################################')
  
  print(ligands_map_mmcif)
  
  print(mmcifdict['_pdbx_nonpoly_scheme.entity_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.pdb_seq_num'])
  print(mmcifdict['_pdbx_nonpoly_scheme.pdb_strand_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.pdb_mon_id'])
  
  ligands_map_pdb = list(zip(mmcifdict['_pdbx_nonpoly_scheme.entity_id'],
                             
                             mmcifdict['_pdbx_nonpoly_scheme.pdb_seq_num'],
                             
                             mmcifdict['_pdbx_nonpoly_scheme.pdb_strand_id'],
                             
                             mmcifdict['_pdbx_nonpoly_scheme.pdb_mon_id']))
  
  print('#########################################')
  
  print(ligands_map_pdb)
  
  
  print('WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWw')
  
  print(mmcifdict['_entity.id'])
  print(mmcifdict['_entity.formula_weight'])
  
  entity_Mw = dict(zip(mmcifdict['_entity.id'],
                       
                       mmcifdict['_entity.formula_weight']))
  
  print(entity_Mw)
  
  print('-------------------------------------------------------------')
  
  
  ligands_map_pdb_red = [i for i in ligands_map_pdb if float(entity_Mw[i[0]]) &gt;= 200 ]
  
  print(ligands_map_pdb_red)
  
  
  
  
  
  #########################################################   first approach 
  
  
  # class ResidueSelect(Select):
  #     def __init__(self, chain, residue):
  #         self.chain = chain
  #         self.residue = residue
  
  #     def accept_chain(self, chain):
      
  #       if chain.id == self.chain.id:
              
  #           return True #1
          
  #       else:
              
  #           return False #0
          
          
  #     def accept_residue(self, residue):
  #         &quot;&quot;&quot; Recognition of heteroatoms - Remove water molecules &quot;&quot;&quot;
          
  #         if residue == self.residue :
              
              
  #             return True #1
          
  #         else:
              
  #             return False #0
  
  
  
  
  # for model in struct:
      
  #     print(model)
      
  #     for chain in model:
          
  #         if chain.id == 'A':
              
  #             for res in chain:
                  
  #                 print(res, res.id, res.get_resname(), type(res))
  
  # i = 1    
  
  # for res in ligands_map_pdb_red :
      
  #     print('\n'+'res : ', res[3], res[0], res[1], type(res[1]), res[2])
      
  #     print(struct[0][res[2]] , type(struct[0][res[2]]) )
      
  #     print(struct[0][res[2]][('H_'+res[3], int(res[1]), ' ')] , type(struct[0][res[2]][('H_'+res[3], int(res[1]), ' ')]) )
      
                  
  #     io = PDBIO()
                      
  #     io.set_structure(struct)
                      
  #     io.save(f&quot;lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb&quot;, ResidueSelect(struct[0][res[2]],
                                                                            
  #                                                     struct[0][res[2]][('H_'+res[3], int(res[1]), ' ')]))
                      
  #     try:
  #         subprocess.run([&quot;openbabel.obabel&quot;, &quot;-ipdb&quot;, f&quot;lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb&quot;, &quot;-osmi&quot; ,&quot;-O&quot;,
                                          
  #         f&quot;lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.smi&quot;])
                          
      
                          
  #     except Exception as excp:
                          
  #         print('\n ', excp, '\n')
                          
                          
                      
  #     i += 1
      
  ########################################################   second approach 
  
  
  import warnings
  
  from Bio import BiopythonWarning
  
  
  def accept_residue_mod(self, residue):
          &quot;&quot;&quot;Verify if a residue sequence is between the start and end sequence.&quot;&quot;&quot;
          # residue - between start and end
          hetatm_flag, resseq, icode = residue.get_id()
          # if hetatm_flag != &quot; &quot;:
          #     # skip HETATMS
          #     return 0
          if icode != &quot; &quot;:
              warnings.warn(
                  f&quot;WARNING: Icode {icode} at position {resseq}&quot;, BiopythonWarning
              )
          if self.start &lt;= resseq &lt;= self.end:
              return 1
          return 0
  
  Dice.ChainSelector.accept_residue = accept_residue_mod
  
  
  i = 1
  
  for res in ligands_map_pdb_red :
      
      print(struct, res[2], int(res[1]), int(res[1]))
  
      Dice.extract(struct, res[2], int(res[1]), int(res[1]), f&quot;lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb&quot;)
      
      
      try:
          subprocess.run([&quot;openbabel.obabel&quot;, &quot;-ipdb&quot;, f&quot;lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb&quot;, &quot;-osmi&quot; ,&quot;-O&quot;,
                                             
          f&quot;lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.smi&quot;])
                              
          
      except Exception as excp:
                              
          print('\n ', excp, '\n')
                              
                              
                          
      i += 1
  
  <span class="math-container">```</span>
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-07T00:30:39.627Z
Answers.LastActivityDate: 2023-01-08T15:20:45.277Z
Answers.LastEditDate: 2023-01-08T15:20:45.277Z
Answers.UserDisplayName: pippo1980
Body: <p>I have some PDB IDs and for every structure, I need all its ligands, so I want to automate the process.</p>
  <p>The ligands are different for every chain:</p>
  <pre><code>$ cat ./7rdx_N_1N7.smi 
  C1[C@@]2(C)[C@@H](C[C@@H](C1)O)[C][C]([C]1[C@H]3[C@]([C@H](C[C]21)O)([C@H](CC3)[C]([C])[C][C])C)O   1N7
  $ cat ./7rdx_U_1N7.smi 
  C1[C@@]2(C)[C@@H](C[C@@H](C1)O)C[C@H]([C@H]1[C@H]3[C@]([C@H](C[C@H]21)O)([C@H](CC3)[C@H](C)CCC(=O)NC[C][C][N+]([C])([C])[C])C)O 1N7
  </code></pre>
  <p>So, I cannot just download the ligands by its name (e.g. <code>https://files.rcsb.org/ligands/download/ZN_ideal.sdf</code>).</p>
  <p>I've tried to find the structures in <em>.pdb</em> file for a given structure, but I see only their names:<br />
  <a href="https://i.sstatic.net/bgwRX.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/bgwRX.png" alt="pdb_file_part" /></a></p>
  <p>Also, as you could see above, I'll convert the <em>.sdf</em> / <em>.mol2</em> files to <em>SMARTS</em> which seems to be a simpler representation - maybe this information'll make the task easier.</p>
  <hr />
  <p>I want to make a script for the process in <em>Python</em>, and the only way to access the <em>RSCB PDB</em> with a library I've found was using <code>biopython</code> but I found there an option to download just a <em>.pdb</em> file (<code>Bio.PDB.PDBList.retrieve_pdb_file</code>), not ligands.</p>
  <p>I've also tried to make my own script, but still I don't know how to access ligands files automatically for every structure. The <em>.pdb</em> files I can access simply by <code>ftp</code> (e.g. <code>https://ftp.wwpdb.org/pub/pdb/data/biounit/PDB/divided/rd/</code>).</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-02T17:03:17.960Z
Comments.Text: How to save each ligand from a PDB file separately with Bio.PDB?  ---> https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-02T17:07:30.723Z
Comments.Text: have a look at ModelServer API too https://models.rcsb.org/#/ and for Pyhton https://github.com/OpenAPITools/openapi-generator
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-02T18:24:02.923Z
Comments.Text: there is a (new for me) https://data.rcsb.org/graphql/index.html GraphQL API : The GraphQL interface offers more flexible data retrieval, essentially making it possible to grab any piece of data from any level of the hierarchy in a single query. To use it programmatically POST your GraphQL queries under the data.rcsb.org/graphql endpoint. No idea how it works but should be the one you are looking for to download all Ligands ??
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-02T18:48:04.363Z
Comments.Text: dont understand what does:  " /v1/{id}/ligand
  Coordinates of the first group satisfying the given criteria."  means for the ModelServerAPI https://models.rcsb.org/#/
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-04T08:11:57.850Z
Comments.Text: Thank you for your response. It seems they meant first ligand for the given structure, but not unique one. I tired it on *7RDZ* and got *ASP* which is not an unique ligand for the structure.
  Still trying to get all unique ligands.
Comments.UserDisplayName: maciejwww
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-04T08:31:52.060Z
Comments.Text: Played a little bit on modelserver with no luck, graphQL should be easier because the test page has autocompletion  but wont work with OpenAPI generator for Python bindings. Ligands used to belong to a Chain in the old PDBs standard now they are non polymer entity or chemical compound so buffer components get mixed up with 'proper' ligands. Need to figure out how to get these entity out from API just sending entry ID and then recover them one by one (for all the Asymmetric units !?) ; not sure it'll be a,less hassle then parsing the full PDBx/mmCIF file
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-04T11:25:30.300Z
Comments.Text: ADDENDUM https://www.apollographql.com/blog/graphql/python/complete-api-guide/ : Using GraphQL with Python – A Complete Guide
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-04T18:57:32.363Z
Comments.Text: Thanks, I'll try to use a query I've made earlier in *GraphiQL*. It seems to provide the ligands in *.smi* format right away.
  Still, I'm curious if it's possible to get the files from the webpage (*.sdf*, *.mol2*) with any *GrapgQL* query.
Comments.UserDisplayName: maciejwww
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-04T20:45:24.273Z
Comments.Text: Found this on rcsb pdb : Ligand of Interest (LOI)
  A small molecule is termed a Ligand of Interest (LOI) when it is the subject of the author’s research rather than a byproduct of the experimental conditions. For example, in entry 1OBV, the small molecule palmitic acid. (PLM) is designated as an LOI as it is bound inside the cavity of the the fatty-acid-binding protein EgFABP1 and is integral to the study. Now need to figure out where LOI is written
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-04T20:54:51.487Z
Comments.Text: Pdb 101 has a typo example pdb is 1O8B not 1OBV
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-04T20:59:57.543Z
Comments.Text: More, I am learning mmcif :  residues/ligands do not have a residue number in mmCIF
Comments.UserDisplayName: pippo1980
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-01-08T09:31:31.077Z
Comments.Text: my memoruy is failing please find this post I tried to answer about 1 year ago https://bioinformatics.stackexchange.com/questions/18076/help-me-in-understanding-the-pdb-file
Comments.UserDisplayName: pippo1980
Tags: <python><pdb><data-download>
Title: How to download ligands for PDB structure
ThreadText: # How to download ligands for PDB structure
  
  (Asked by: username_0 on 2023-01-02)
  
  I have some PDB IDs and for every structure, I need all its ligands, so I want to automate the process.
  
  The ligands are different for every chain:
  
  ```
  $ cat ./7rdx_N_1N7.smi 
  C1[C@@]2(C)[C@@H](C[C@@H](C1)O)[C][C]([C]1[C@H]3[C@]([C@H](C[C]21)O)([C@H](CC3)[C]([C])[C][C])C)O   1N7
  $ cat ./7rdx_U_1N7.smi 
  C1[C@@]2(C)[C@@H](C[C@@H](C1)O)C[C@H]([C@H]1[C@H]3[C@]([C@H](C[C@H]21)O)([C@H](CC3)[C@H](C)CCC(=O)NC[C][C][N+]([C])([C])[C])C)O 1N7
  
  ```
  
  So, I cannot just download the ligands by its name (e.g. `https://files.rcsb.org/ligands/download/ZN_ideal.sdf`).
  
  I've tried to find the structures in *.pdb* file for a given structure, but I see only their names:  
  [![pdb_file_part](https://i.sstatic.net/bgwRX.png)](https://i.sstatic.net/bgwRX.png)
  
  Also, as you could see above, I'll convert the *.sdf* / *.mol2* files to *SMARTS* which seems to be a simpler representation - maybe this information'll make the task easier.
  
  ---
  
  I want to make a script for the process in *Python*, and the only way to access the *RSCB PDB* with a library I've found was using `biopython` but I found there an option to download just a *.pdb* file (`Bio.PDB.PDBList.retrieve_pdb_file`), not ligands.
  
  I've also tried to make my own script, but still I don't know how to access ligands files automatically for every structure. The *.pdb* files I can access simply by `ftp` (e.g. `https://ftp.wwpdb.org/pub/pdb/data/biounit/PDB/divided/rd/`).
  
  **Tags:** python, pdb, data-download
  
  > **Comments:**
  > **username_1**: How to save each ligand from a PDB file separately with Bio.PDB?  ---> https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb  
  > **username_1**: have a look at ModelServer API too https://models.rcsb.org/#/ and for Pyhton https://github.com/OpenAPITools/openapi-generator  
  > **username_1**: there is a (new for me) https://data.rcsb.org/graphql/index.html GraphQL API : The GraphQL interface offers more flexible data retrieval, essentially making it possible to grab any piece of data from any level of the hierarchy in a single query. To use it programmatically POST your GraphQL queries under the data.rcsb.org/graphql endpoint. No idea how it works but should be the one you are looking for to download all Ligands ??  
  > **username_1**: dont understand what does:  " /v1/{id}/ligand Coordinates of the first group satisfying the given criteria."  means for the ModelServerAPI https://models.rcsb.org/#/  
  > **username_0**: Thank you for your response. It seems they meant first ligand for the given structure, but not unique one. I tired it on *7RDZ* and got *ASP* which is not an unique ligand for the structure. Still trying to get all unique ligands.  
  > **username_1**: Played a little bit on modelserver with no luck, graphQL should be easier because the test page has autocompletion  but wont work with OpenAPI generator for Python bindings. Ligands used to belong to a Chain in the old PDBs standard now they are non polymer entity or chemical compound so buffer components get mixed up with 'proper' ligands. Need to figure out how to get these entity out from API just sending entry ID and then recover them one by one (for all the Asymmetric units !?) ; not sure it'll be a,less hassle then parsing the full PDBx/mmCIF file  
  > **username_1**: ADDENDUM https://www.apollographql.com/blog/graphql/python/complete-api-guide/ : Using GraphQL with Python – A Complete Guide  
  > **username_0**: Thanks, I'll try to use a query I've made earlier in *GraphiQL*. It seems to provide the ligands in *.smi* format right away. Still, I'm curious if it's possible to get the files from the webpage (*.sdf*, *.mol2*) with any *GrapgQL* query.  
  > **username_1**: Found this on rcsb pdb : Ligand of Interest (LOI) A small molecule is termed a Ligand of Interest (LOI) when it is the subject of the author’s research rather than a byproduct of the experimental conditions. For example, in entry 1OBV, the small molecule palmitic acid. (PLM) is designated as an LOI as it is bound inside the cavity of the the fatty-acid-binding protein EgFABP1 and is integral to the study. Now need to figure out where LOI is written  
  > **username_1**: Pdb 101 has a typo example pdb is 1O8B not 1OBV  
  > **username_1**: More, I am learning mmcif :  residues/ligands do not have a residue number in mmCIF  
  > **username_1**: my memoruy is failing please find this post I tried to answer about 1 year ago https://bioinformatics.stackexchange.com/questions/18076/help-me-in-understanding-the-pdb-file  
  
  ---
  
  ## 4 answers
  
  ### Answer by username_2 on 2023-03-09. Score: 1
  
  Here can use GraphiQL API provided by RCSB.
  Here is an example
  
  ```py
  import requests
  from rdkit import Chem
  pdbid = '7RDX'
  ls_smi = []
  
  query = f'''{{
    entry(entry_id: "{pdbid}") {{
      nonpolymer_entities {{
        nonpolymer_comp {{
          rcsb_id
          pdbx_chem_comp_descriptor {{
            type
            comp_id
            program
            descriptor
          }}
        }}
      }}
    }}
  }}'''
  url = "https://data.rcsb.org/graphql"
  r = requests.post(url, json={'query': query})
  for i in r.json()['data']['entry']['nonpolymer_entities']:
      if i['nonpolymer_comp']['pdbx_chem_comp_descriptor'][0]['type'] == 'SMILES':
          ls_smi.append(Chem.CanonSmiles(i['nonpolymer_comp']['pdbx_chem_comp_descriptor'][0]['descriptor']))
  
  ```
  
  > **Comments:**
  > **username_3**: Thanks @username_2 and welcome to the site. A good answer  
  
  ---
  
  ### Answer by username_1 on 2023-01-08. Score: 1
  
  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](https://bioinformatics.stackexchange.com/questions/18076/help-me-in-understanding-the-pdb-file).
  
  So inspecting and copying directly from the PDB entry [7RDX](https://www.rcsb.org/structure/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.sdf>I 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.
  
  
  ---
  
  ### Answer by username_1 on 2023-01-05. Score: 1
  
  Ok, cannot try the API approach, no resources during vacation. Got the download and parse/split approach, added conversion to SMILES by **Openbabel**. I believe it is exactly the same question of : <https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb> from where I stole the juicy bit of the code:
  
  ```
  ## stealing from https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb
  
  from Bio import __version__
  
  print('BIOPYTHON Version : ' , __version__)
  
  from Bio.PDB import MMCIFParser, PDBIO, Select, PDBList
  
  import subprocess
  
  filename = '7rdx.cif'
  
  pdblist = PDBList()
  
  pdblist.retrieve_pdb_file(filename.upper().split('.')[0] , pdir = '.')
  
  pars = MMCIFParser(QUIET = True)
  
  struct = pars.get_structure('7rdx',  filename)
  
  print(struct, type(struct))
  
  def is_het(residue):
      res = residue.id[0]
      
      if res != " " and res != "W":
          
          return True #1
  
      else:
      
          return False #0
   
  
  class ResidueSelect(Select):
      def __init__(self, chain, residue):
          self.chain = chain
          self.residue = residue
  
      def accept_chain(self, chain):
      
          if chain.id == self.chain.id:
              
              return True #1
          
          else:
              
              return False #0
          
          
      def accept_residue(self, residue):
          """ Recognition of heteroatoms - Remove water molecules """
          
          if residue == self.residue and is_het(residue):
              
              return True #1
          
          else:
              
              return False #0
  
  for model in struct :
      
      
      dizio = model.child_dict
      
      print('\n'+ str(dizio))
      
      
  
  for model in struct:
      
      i = 1
      
      print(model, model.id)
      
      for chain in model:
          
          print(chain, chain.id)
          
          for res in chain:
              
              # print('\n'+'res : ', res, 'res.resname : ', res.resname)
              
              if res.id[0] != " " :
                  
                  
                  print('\n'+'res : ', res, res.id, res.resname)
                  
                  io = PDBIO()
                  
                  io.set_structure(struct)
                  
                  io.save(f"lig_{chain.id}_{res.resname}_{i}.pdb", ResidueSelect(chain, res))
                  
                  try:
                      subprocess.run(["openbabel.obabel", "-ipdb", f"lig_{chain.id}_{res.resname}_{i}.pdb", "-osmi" ,"-O",
                                      
                                      f"lig_{chain.id}_{res.resname}_{i}.smi"])
                      
  
                      
                  except Exception as excp:
                      
                      print('\n ', excp, '\n')
                      
                      
                  
                  i += 1
  
  ```
  
  Problem is Biopython parses **mmCIF**s files; that are now the official standard for RCSB PDB [**Submission of PDBx/mmCIF format files for crystallographic depositions to the PDB will be mandatory from July 1st 2019 onward**. PDB format files will no longer be accepted for deposition of structures solved by MX techniques.](https://www.rcsb.org/news/feature/5c767ef5ea7d0653b99c876f) A nice review about the long history of the 'new' format :[ [PDBx/mmCIF Ecosystem: Foundational Semantic Tools for Structural Biology](https://www.sciencedirect.com/science/article/pii/S0022283622001796?via%3Dihub).
  
  Unfortunately the `Bio.PDB.MMCIFParser module` return a a structure that is:
  
  `<Structure id=7rdx> <class 'Bio.PDB.Structure.Structure'>` so all the ligands are related to PDB chains classification and not PDBx entity.
  
  I could be wrong here, I am a novice in both Biopython and Structural Bioinformatics but this is what I've noticed, please feel free to elaborate on this and add a solution using the RCSB APIes ... before curiosity kills the cat
  
  PS:
  
  **NEEDs to be tested with sample containing water**
  
  
  ---
  
  ### Answer by username_1 on 2023-01-07. Score: 1
  
  adding a different way to solve the question , still without using RCSB PDB database, but using `Biopython.PDB.MMCIF2Dict` module to start to get a feeling on how info are stored in .cif format files. Ligands are selected amongs the ones in the structure for their Mw.
  
  Ligands are then saved using the same approach of first answer or a new one that takes advantage of `Biopython.PDB.Dice` module to extract and save portion of PDB. Again Openbabel is used to translate PDBs to SMILES.
  
  Code :
  
  ```
  #!/usr/bin/env python3
  # -*- coding: utf-8 -*-
  """
  Created on Thu Jan  5 11:43:07 2023
  
  @author: bob
  
  https://bioinformatics.stackexchange.com/questions/20301/how-to-download-ligands-for-pdb-structure?noredirect=1#comment29972_20301
  
  NEEDs to be tested with sample containing water
  
  """
  
  ## stealing from https://stackoverflow.com/questions/61390035/how-to-save-each-ligand-from-a-pdb-file-separately-with-bio-pdb
  
  from Bio import __version__
  
  print('BIOPYTHON Version : ' , __version__)
  
  from Bio.PDB import (
                      MMCIFParser, 
                      PDBIO, 
                      Select, 
                      PDBList, 
                      MMCIF2Dict,
                      Dice
                      )
  
  import subprocess
  
  filename = '7rdx.cif'
  
  # filename = '7RDX.cif'  # this will  work , but biopython saves in lower case 
  
  # pdblist = PDBList()
  
  # pdblist.retrieve_pdb_file(filename.split('.')[0] , pdir = '.')
  
  pars = MMCIFParser(QUIET = True)
  
  struct = pars.get_structure('7rdx',  filename)
  
  # print(struct, type(struct))
  
  mmcifdict = MMCIF2Dict.MMCIF2Dict(filename)
  
  # print(mmcifdict)
  
  # for i in mmcifdict:
      
  #     print('\n', i ,'   ---> ', mmcifdict[i])
      
  print('##############################################################')
      
  # print(mmcifdict['_entity'])
  
   
  print(mmcifdict['_pdbx_nonpoly_scheme.entity_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.asym_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.entity_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.mon_id'])
  
  ligands_map_mmcif = list(zip(mmcifdict['_pdbx_nonpoly_scheme.entity_id'],
                               
                               mmcifdict['_pdbx_nonpoly_scheme.asym_id'],
                               
                               mmcifdict['_pdbx_nonpoly_scheme.entity_id'],
                               
                               mmcifdict['_pdbx_nonpoly_scheme.mon_id']))
  
  print('#########################################')
  
  print(ligands_map_mmcif)
  
  print(mmcifdict['_pdbx_nonpoly_scheme.entity_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.pdb_seq_num'])
  print(mmcifdict['_pdbx_nonpoly_scheme.pdb_strand_id'])
  print(mmcifdict['_pdbx_nonpoly_scheme.pdb_mon_id'])
  
  ligands_map_pdb = list(zip(mmcifdict['_pdbx_nonpoly_scheme.entity_id'],
                             
                             mmcifdict['_pdbx_nonpoly_scheme.pdb_seq_num'],
                             
                             mmcifdict['_pdbx_nonpoly_scheme.pdb_strand_id'],
                             
                             mmcifdict['_pdbx_nonpoly_scheme.pdb_mon_id']))
  
  print('#########################################')
  
  print(ligands_map_pdb)
  
  print('WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWw')
  
  print(mmcifdict['_entity.id'])
  print(mmcifdict['_entity.formula_weight'])
  
  entity_Mw = dict(zip(mmcifdict['_entity.id'],
                       
                       mmcifdict['_entity.formula_weight']))
  
  print(entity_Mw)
  
  print('-------------------------------------------------------------')
  
  ligands_map_pdb_red = [i for i in ligands_map_pdb if float(entity_Mw[i[0]]) >= 200 ]
  
  print(ligands_map_pdb_red)
  
  #########################################################   first approach 
  
  # class ResidueSelect(Select):
  #     def __init__(self, chain, residue):
  #         self.chain = chain
  #         self.residue = residue
  
  #     def accept_chain(self, chain):
      
  #       if chain.id == self.chain.id:
              
  #           return True #1
          
  #       else:
              
  #           return False #0
          
          
  #     def accept_residue(self, residue):
  #         """ Recognition of heteroatoms - Remove water molecules """
          
  #         if residue == self.residue :
              
              
  #             return True #1
          
  #         else:
              
  #             return False #0
  
  # for model in struct:
      
  #     print(model)
      
  #     for chain in model:
          
  #         if chain.id == 'A':
              
  #             for res in chain:
                  
  #                 print(res, res.id, res.get_resname(), type(res))
  
  # i = 1    
  
  # for res in ligands_map_pdb_red :
      
  #     print('\n'+'res : ', res[3], res[0], res[1], type(res[1]), res[2])
      
  #     print(struct[0][res[2]] , type(struct[0][res[2]]) )
      
  #     print(struct[0][res[2]][('H_'+res[3], int(res[1]), ' ')] , type(struct[0][res[2]][('H_'+res[3], int(res[1]), ' ')]) )
      
                  
  #     io = PDBIO()
                      
  #     io.set_structure(struct)
                      
  #     io.save(f"lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb", ResidueSelect(struct[0][res[2]],
                                                                            
  #                                                     struct[0][res[2]][('H_'+res[3], int(res[1]), ' ')]))
                      
  #     try:
  #         subprocess.run(["openbabel.obabel", "-ipdb", f"lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb", "-osmi" ,"-O",
                                          
  #         f"lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.smi"])
                          
      
                          
  #     except Exception as excp:
                          
  #         print('\n ', excp, '\n')
                          
                          
                      
  #     i += 1
      
  ########################################################   second approach 
  
  import warnings
  
  from Bio import BiopythonWarning
  
  def accept_residue_mod(self, residue):
          """Verify if a residue sequence is between the start and end sequence."""
          # residue - between start and end
          hetatm_flag, resseq, icode = residue.get_id()
          # if hetatm_flag != " ":
          #     # skip HETATMS
          #     return 0
          if icode != " ":
              warnings.warn(
                  f"WARNING: Icode {icode} at position {resseq}", BiopythonWarning
              )
          if self.start <= resseq <= self.end:
              return 1
          return 0
  
  Dice.ChainSelector.accept_residue = accept_residue_mod
  
  i = 1
  
  for res in ligands_map_pdb_red :
      
      print(struct, res[2], int(res[1]), int(res[1]))
  
      Dice.extract(struct, res[2], int(res[1]), int(res[1]), f"lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb")
      
      
      try:
          subprocess.run(["openbabel.obabel", "-ipdb", f"lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.pdb", "-osmi" ,"-O",
                                             
          f"lig_{res[3]}_{res[2]}_{str(i).zfill(5)}.smi"])
                              
          
      except Exception as excp:
                              
          print('\n ', excp, '\n')
                              
                              
                          
      i += 1
  
  ```
  
  ```
  
  
  ---
  
  