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