The other answer is correct. But I thought I'd give a few pointers in how one can understand how to do something with a given Python module —teach a man to fish kind of thing...
In a Jupyter Notebook or IPython shell (don't), you can do:
help(function)
print out the docstring
dir(object)
shows all the public and magic attributes and methods —note a class will not show the instance methods
type(object)
or object.__class__
gives you what the class is, but object.__class__.__mro__
tells you what it inherits.
- in the standard library module
inspect
is the function inspect.getsource(function)
, which for a notebook is messy due to newlines so needs to be print_code = lambda fun: print(inspect.getsource(fun))
and print_code(fun)
.
In your case you read a file...
from Bio import PDB
parser = PDB.PDBParser()
structure : PDB.Structure.Structure = parser.get_structure("tryp-cage", "1L2Y.first.pdb")
So parser.get_structure
"magically" makes a structure, eh? This means it can add stuff! As mentioned print_code(parser.get_structure)
will reveal its secrets, or within it call some self._private_fun()
, which can be inspected (self
= parser
) all the way down the rabbit hole. Until you find a nice constructor that declares nicely an atom instance or whatever you ever fancy searching for —that is the great thing of open source code.
In the specific case of PDB
module, everything inherits Entity
, which has the attribute child_list
, which is what the iterators (__iter__
is the topmost) read without making a copy. The end of the above rabbit hole may just add a child Entity
-inheriting class instance to this list, but it also do other things that is worth keeping an eye out.
In the case of residue.add(atom)
, creating the Bio.PDB.Atom.Atom
instance is slightly problematic as there's no typehinting or :type xxx:
declarations in the docstring. But doing type(atom.bfactor)
etc. on the attributes of an existing atom will reveal how to do it. One the serial number is a PDB thing, which is sequential for the model.
last_serial = list(structure.get_residues())[-1].child_list[-1].serial_number + 1
residue.add(PDB.Atom.Atom(name=' H ', coord=np.array([1,1,1]), bfactor=0., occupancy=1., altloc=' ', fullname=' H ', serial_number=last_serial+1,element='H'))
The coordinates will not be [1,1,1]
, but the point that you have calculate. Say for H
, this would be coplanar with C
, CA
and N
, that is 1 and smidge Å away from N
at an angle not quite in the middle as found in amide bonds.