I have a list of PDB files. I want to extract the ligands of all the files (so, heteroatoms) and save each one separately into PDB files, by using the Bio.PDB module from BioPython.
I tried some solutions, like this one: Remove heteroatoms from PDB , that I tried to adapt to keep the heteroatoms. But all I obtain is files with all the ligand in the same file.
I also tried a thing like this :
def accept_residue(residue):
""" Recognition of heteroatoms - Remove water molecules """
res = residue.id[0]
if res != " ": # Heteroatoms have some flags, that's why we keep only residue with id != " "
if res != "W": # Don't take in consideration the water molecules
return True
def extract_ligands(path):
""" Extraction of the heteroatoms of .pdb files """
for element in os.listdir(path+'/data/pdb'):
i=1
if element.endswith('.pdb'):
if not element.startswith("lig_"):
pdb = PDBParser().get_structure(element[:-4], path+'/data/pdb/'+element)
io = PDBIO()
io.set_structure(pdb)
for model in pdb:
for chain in model:
for residue in chain:
if accept_residue(residue):
io.save("lig_"+element[:-4]+"_"+str(i)+".pdb", accept_residue(residue))
i += 1 # Counter for the result filename
# Main
path = mypath
extract_ligands(path)
Obviously, it raised an error :
AttributeError: 'bool' object has no attribute 'accept_model'
I know that's because of the "accept_residue()" in my "io.save". But I didn't find any logical solution to do what I want to...
At last, I tried a solution like this one, with chain.detach_child() :
...
for chain in model:
for residue in chain:
res = residue.id[0]
if res == " " or res == "W":
chain.detach_child(residue.id)
if len(chain) == 0:
model.detach_child(chain.id)
...
In my mind, it would "detach" all the residues that are not heteroatoms ( res.id[0] == " " ) and all the water ( res.id[0] == "W"). But in fine, all the residues and water are still there and buggy.
So, is it possible to do what I need? ( extract all ligands from all my files and save it one by one separately in PDB files)