Reputation: 307
Using biopython library, I want to remove the residues that are listed in list as follows. This thread (http://pelican.rsvs.ulaval.ca/mediawiki/index.php/Manipulating_PDB_files_using_BioPython) provides an example to remove residue. I have following code to remove residues
residue_ids_to_remove = [105, 5, 8, 10, 25, 48]
structure = pdbparser.get_structure("3chy", "./3chy.pdb")
first_model = structure[0]
for chain in first_model:
for residue in chain:
id = residue.id
if id[1] in residue_ids_to_remove:
chain.detach_child(id[1])
modified_first_model = first_model
But this code did not work and raised the error
def detach_child(self, id):
"Remove a child."
child=self.child_dict[id]
KeyError: '105'
What's wrong with this code?
Alternatively, I can do using accept_residue() and write it in PDB. I don't want to follow like this becauseI want to do it while in memory for further processing.
Upvotes: 5
Views: 3204
Reputation: 7443
Biopython cannot find the key in the inner dictionary to the chain, because you're supplying a random key. The dict looks like this:
child_dict = {(' ', 5, ' '): <Residue HOH het=W resseq=5 icode= >,
(' ', 6, ' '): <Residue HOH het=W resseq=6 icode= >,
(' ', 7, ' '): <Residue HOH het=W resseq=7 icode= >}
That is: using tuples as dict keys. You can see the dict doing print chain.child_dict
.
Once you know this, the error/solution is clear. Pass a valid key to detach_child
, namely remove the [1]
:
if id[1] in residue_ids_to_remove:
chain.detach_child(id)
Detach the children from the chain level, and do not cycle the residues directly:
for chain in first model:
for id in residue_ids_to_remove:
chain.detach_child((' ', id, ' '))
Or with list comprehension:
for chain in first_model:
[chain.detach_child((' ', id, ' ')) for id in residue_ids_to_remove]
Upvotes: 5