Package Bio :: Package PDB :: Module StructureBuilder
[hide private]
[frames] | no frames]

Source Code for Module Bio.PDB.StructureBuilder

  1  # Copyright (C) 2002, Thomas Hamelryck (thamelry@binf.ku.dk) 
  2  # This code is part of the Biopython distribution and governed by its 
  3  # license.  Please see the LICENSE file that should have been included 
  4  # as part of this package. 
  5   
  6  """Consumer class that builds a Structure object. 
  7   
  8  This is used by the PDBParser and MMCIFparser classes. 
  9  """ 
 10   
 11  import warnings 
 12   
 13  # SMCRA hierarchy 
 14  from Bio.PDB.Structure import Structure 
 15  from Bio.PDB.Model import Model 
 16  from Bio.PDB.Chain import Chain 
 17  from Bio.PDB.Residue import Residue, DisorderedResidue 
 18  from Bio.PDB.Atom import Atom, DisorderedAtom 
 19   
 20  from Bio.PDB.PDBExceptions import PDBConstructionException 
 21  from Bio.PDB.PDBExceptions import PDBConstructionWarning 
 22   
 23  __docformat__ = "restructuredtext en" 
 24   
 25   
26 -class StructureBuilder(object):
27 """ 28 Deals with contructing the Structure object. The StructureBuilder class is used 29 by the PDBParser classes to translate a file to a Structure object. 30 """
31 - def __init__(self):
32 self.line_counter = 0 33 self.header = {}
34
35 - def _is_completely_disordered(self, residue):
36 "Return 1 if all atoms in the residue have a non blank altloc." 37 atom_list = residue.get_unpacked_list() 38 for atom in atom_list: 39 altloc = atom.get_altloc() 40 if altloc == " ": 41 return 0 42 return 1
43 44 # Public methods called by the Parser classes 45
46 - def set_header(self, header):
47 self.header = header
48
49 - def set_line_counter(self, line_counter):
50 """ 51 The line counter keeps track of the line in the PDB file that 52 is being parsed. 53 54 Arguments: 55 o line_counter - int 56 """ 57 self.line_counter = line_counter
58
59 - def init_structure(self, structure_id):
60 """Initiate a new Structure object with given id. 61 62 Arguments: 63 o id - string 64 """ 65 self.structure = Structure(structure_id)
66
67 - def init_model(self, model_id, serial_num=None):
68 """Initiate a new Model object with given id. 69 70 Arguments: 71 o id - int 72 o serial_num - int 73 """ 74 self.model = Model(model_id, serial_num) 75 self.structure.add(self.model)
76
77 - def init_chain(self, chain_id):
78 """Initiate a new Chain object with given id. 79 80 Arguments: 81 o chain_id - string 82 """ 83 if self.model.has_id(chain_id): 84 self.chain = self.model[chain_id] 85 warnings.warn("WARNING: Chain %s is discontinuous at line %i." 86 % (chain_id, self.line_counter), 87 PDBConstructionWarning) 88 else: 89 self.chain = Chain(chain_id) 90 self.model.add(self.chain)
91
92 - def init_seg(self, segid):
93 """Flag a change in segid. 94 95 Arguments: 96 o segid - string 97 """ 98 self.segid = segid
99
100 - def init_residue(self, resname, field, resseq, icode):
101 """ 102 Initiate a new Residue object. 103 104 Arguments: 105 106 - resname - string, e.g. "ASN" 107 - field - hetero flag, "W" for waters, "H" for 108 hetero residues, otherwise blank. 109 - resseq - int, sequence identifier 110 - icode - string, insertion code 111 """ 112 if field != " ": 113 if field == "H": 114 # The hetero field consists of H_ + the residue name (e.g. H_FUC) 115 field = "H_" + resname 116 res_id = (field, resseq, icode) 117 if field == " ": 118 if self.chain.has_id(res_id): 119 # There already is a residue with the id (field, resseq, icode). 120 # This only makes sense in the case of a point mutation. 121 warnings.warn("WARNING: Residue ('%s', %i, '%s') " 122 "redefined at line %i." 123 % (field, resseq, icode, self.line_counter), 124 PDBConstructionWarning) 125 duplicate_residue = self.chain[res_id] 126 if duplicate_residue.is_disordered() == 2: 127 # The residue in the chain is a DisorderedResidue object. 128 # So just add the last Residue object. 129 if duplicate_residue.disordered_has_id(resname): 130 # The residue was already made 131 self.residue = duplicate_residue 132 duplicate_residue.disordered_select(resname) 133 else: 134 # Make a new residue and add it to the already 135 # present DisorderedResidue 136 new_residue = Residue(res_id, resname, self.segid) 137 duplicate_residue.disordered_add(new_residue) 138 self.residue = duplicate_residue 139 return 140 else: 141 if resname == duplicate_residue.resname: 142 warnings.warn("WARNING: Residue ('%s', %i, '%s','%s')" 143 " already defined with the same name at line %i." 144 % (field, resseq, icode, resname, self.line_counter), 145 PDBConstructionWarning) 146 self.residue = duplicate_residue 147 return 148 # Make a new DisorderedResidue object and put all 149 # the Residue objects with the id (field, resseq, icode) in it. 150 # These residues each should have non-blank altlocs for all their atoms. 151 # If not, the PDB file probably contains an error. 152 if not self._is_completely_disordered(duplicate_residue): 153 # if this exception is ignored, a residue will be missing 154 self.residue = None 155 raise PDBConstructionException( 156 "Blank altlocs in duplicate residue %s ('%s', %i, '%s')" 157 % (resname, field, resseq, icode)) 158 self.chain.detach_child(res_id) 159 new_residue = Residue(res_id, resname, self.segid) 160 disordered_residue = DisorderedResidue(res_id) 161 self.chain.add(disordered_residue) 162 disordered_residue.disordered_add(duplicate_residue) 163 disordered_residue.disordered_add(new_residue) 164 self.residue = disordered_residue 165 return 166 self.residue = Residue(res_id, resname, self.segid) 167 self.chain.add(self.residue)
168
169 - def init_atom(self, name, coord, b_factor, occupancy, altloc, fullname, 170 serial_number=None, element=None):
171 """ 172 Initiate a new Atom object. 173 174 Arguments: 175 o name - string, atom name, e.g. CA, spaces should be stripped 176 o coord - Numeric array (Float0, size 3), atomic coordinates 177 o b_factor - float, B factor 178 o occupancy - float 179 o altloc - string, alternative location specifier 180 o fullname - string, atom name including spaces, e.g. " CA " 181 o element - string, upper case, e.g. "HG" for mercury 182 """ 183 residue = self.residue 184 # if residue is None, an exception was generated during 185 # the construction of the residue 186 if residue is None: 187 return 188 # First check if this atom is already present in the residue. 189 # If it is, it might be due to the fact that the two atoms have atom 190 # names that differ only in spaces (e.g. "CA.." and ".CA.", 191 # where the dots are spaces). If that is so, use all spaces 192 # in the atom name of the current atom. 193 if residue.has_id(name): 194 duplicate_atom = residue[name] 195 # atom name with spaces of duplicate atom 196 duplicate_fullname = duplicate_atom.get_fullname() 197 if duplicate_fullname != fullname: 198 # name of current atom now includes spaces 199 name = fullname 200 warnings.warn("Atom names %r and %r differ " 201 "only in spaces at line %i." 202 % (duplicate_fullname, fullname, 203 self.line_counter), 204 PDBConstructionWarning) 205 self.atom = Atom(name, coord, b_factor, occupancy, altloc, 206 fullname, serial_number, element) 207 if altloc != " ": 208 # The atom is disordered 209 if residue.has_id(name): 210 # Residue already contains this atom 211 duplicate_atom = residue[name] 212 if duplicate_atom.is_disordered() == 2: 213 duplicate_atom.disordered_add(self.atom) 214 else: 215 # This is an error in the PDB file: 216 # a disordered atom is found with a blank altloc 217 # Detach the duplicate atom, and put it in a 218 # DisorderedAtom object together with the current 219 # atom. 220 residue.detach_child(name) 221 disordered_atom = DisorderedAtom(name) 222 residue.add(disordered_atom) 223 disordered_atom.disordered_add(self.atom) 224 disordered_atom.disordered_add(duplicate_atom) 225 residue.flag_disordered() 226 warnings.warn("WARNING: disordered atom found " 227 "with blank altloc before line %i.\n" 228 % self.line_counter, 229 PDBConstructionWarning) 230 else: 231 # The residue does not contain this disordered atom 232 # so we create a new one. 233 disordered_atom = DisorderedAtom(name) 234 residue.add(disordered_atom) 235 # Add the real atom to the disordered atom, and the 236 # disordered atom to the residue 237 disordered_atom.disordered_add(self.atom) 238 residue.flag_disordered() 239 else: 240 # The atom is not disordered 241 residue.add(self.atom)
242
243 - def set_anisou(self, anisou_array):
244 "Set anisotropic B factor of current Atom." 245 self.atom.set_anisou(anisou_array)
246
247 - def set_siguij(self, siguij_array):
248 "Set standard deviation of anisotropic B factor of current Atom." 249 self.atom.set_siguij(siguij_array)
250
251 - def set_sigatm(self, sigatm_array):
252 "Set standard deviation of atom position of current Atom." 253 self.atom.set_sigatm(sigatm_array)
254
255 - def get_structure(self):
256 "Return the structure." 257 # first sort everything 258 # self.structure.sort() 259 # Add the header dict 260 self.structure.header = self.header 261 return self.structure
262
263 - def set_symmetry(self, spacegroup, cell):
264 pass
265