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