I have a pdb containing a protein and one single ligand. I do not like how the ligand's hydrogens are named (1H2, 2H2, 1H3, 2H3, ...) and I would like something like H1, H2, H3, H4, ...
I wrote the following script, the problem is that it seems it's not possible to assign new atom ids. The change is reflected by Atom.id, but this change is not present in the output pdb structure, which retains the old names.
from Bio.PDB import PDBParser, PDBIO
io = PDBIO()
target_pdb_path = 'mypdb.pdb'
pdb = PDBParser(QUIET=True).get_structure('target', target_pdb_path)[0]
hydrogens = []
for atom in pdb.get_atoms():
if atom.parent.id[0].startswith('H_'):
# The atom is an hydrogen and is an HETATM record
if 'H' in atom.name:
hydrogens.append(atom)
# Rename hydrogens of the ligand
for h_num, h in enumerate(hydrogens, 1):
# this is working, but the change is not present in the output pdb structure
h.id = f'H{h_num} '
io.set_structure(pdb)
io.save('test.pdb')
See how assigning h.id did not change the full_id. I tried also replacing the whole full_id tuple, but also this does not work. Unfortunately it seems there's no method to change the id just like other features as Atom.set_bfactor(), Atom.set_coord() etc.
In [233]: h.full_id # still the old id 3H18
Out[233]: ('target', 0, 'X', ('H_EOD', 401, ' '), ('3H18', ' '))
In [234]: h.id # my new id
Out[234]: 'H29 '
Does anyone have a solution? Many thanks!

Given @nannarito concerns, I tried to find a way that doesn't need creating new
Atomobjects, I wasn't able to get a grasp of what goes behind the wheels of Biopython PDB module (I tried but it eludes me). After various attempts I ended up with the following code:Using same input of answer above I get as output file
test_new_approach.pdb:So
setattr( h , 'fullname' , f'W{h_num}' )seems to do the trick, but for some reasons inexplicable to me, this:bit, used after the
setattr( h , 'fullname' , f'W{h_num}' )before or after the:still produces:
... the original question gets more intriguing.
I think I got something more:
needed to add
h.name = f'W{h_num}'too, like:to have:
when using:
so
h.get_full_id()returns the updated atom namebut still get old
h.idwhen using:.. so to me it's like something is going on on the
Structureobject and its parent/child relationships, since it can be corrected by using:but still
atom.iddoesn't get reinitialized, see:Output:
In the end, try using:
... but cannot guarantee that something somewhere isn't wrong.