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 blanc 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 blanc. 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-blanc 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, "Blank altlocs in duplicate residue %s ('%s', %i, '%s')" % (resname, field, resseq, icode) 146 self.chain.detach_child(res_id) 147 new_residue=Residue(res_id, resname, self.segid) 148 disordered_residue=DisorderedResidue(res_id) 149 self.chain.add(disordered_residue) 150 disordered_residue.disordered_add(duplicate_residue) 151 disordered_residue.disordered_add(new_residue) 152 self.residue=disordered_residue 153 return 154 residue=Residue(res_id, resname, self.segid) 155 self.chain.add(residue) 156 self.residue=residue
157
158 - def init_atom(self, name, coord, b_factor, occupancy, altloc, fullname, serial_number=None):
159 """ 160 Initiate a new Atom object. 161 162 Arguments: 163 o name - string, atom name, e.g. CA, spaces should be stripped 164 o coord - Numeric array (Float0, size 3), atomic coordinates 165 o b_factor - float, B factor 166 o occupancy - float 167 o altloc - string, alternative location specifier 168 o fullname - string, atom name including spaces, e.g. " CA " 169 """ 170 residue=self.residue 171 # if residue is None, an exception was generated during 172 # the construction of the residue 173 if residue is None: 174 return 175 # First check if this atom is already present in the residue. 176 # If it is, it might be due to the fact that the two atoms have atom 177 # names that differ only in spaces (e.g. "CA.." and ".CA.", 178 # where the dots are spaces). If that is so, use all spaces 179 # in the atom name of the current atom. 180 if residue.has_id(name): 181 duplicate_atom=residue[name] 182 # atom name with spaces of duplicate atom 183 duplicate_fullname=duplicate_atom.get_fullname() 184 if duplicate_fullname!=fullname: 185 # name of current atom now includes spaces 186 name=fullname 187 if __debug__: 188 sys.stderr.write("WARNING: atom names %s and %s differ only in spaces at line %i.\n" 189 % (duplicate_fullname, fullname, self.line_counter)) 190 atom=self.atom=Atom(name, coord, b_factor, occupancy, altloc, fullname, serial_number) 191 if altloc!=" ": 192 # The atom is disordered 193 if residue.has_id(name): 194 # Residue already contains this atom 195 duplicate_atom=residue[name] 196 if duplicate_atom.is_disordered()==2: 197 duplicate_atom.disordered_add(atom) 198 else: 199 # This is an error in the PDB file: 200 # a disordered atom is found with a blanc altloc 201 # Detach the duplicate atom, and put it in a 202 # DisorderedAtom object together with the current 203 # atom. 204 residue.detach_child(name) 205 disordered_atom=DisorderedAtom(name) 206 residue.add(disordered_atom) 207 disordered_atom.disordered_add(atom) 208 disordered_atom.disordered_add(duplicate_atom) 209 residue.flag_disordered() 210 if __debug__: 211 sys.stderr.write("WARNING: disordered atom found with blanc altloc before line %i.\n" 212 % self.line_counter) 213 else: 214 # The residue does not contain this disordered atom 215 # so we create a new one. 216 disordered_atom=DisorderedAtom(name) 217 residue.add(disordered_atom) 218 # Add the real atom to the disordered atom, and the 219 # disordered atom to the residue 220 disordered_atom.disordered_add(atom) 221 residue.flag_disordered() 222 else: 223 # The atom is not disordered 224 residue.add(atom)
225
226 - def set_anisou(self, anisou_array):
227 "Set anisotropic B factor of current Atom." 228 self.atom.set_anisou(anisou_array)
229
230 - def set_siguij(self, siguij_array):
231 "Set standard deviation of anisotropic B factor of current Atom." 232 self.atom.set_siguij(siguij_array)
233
234 - def set_sigatm(self, sigatm_array):
235 "Set standard deviation of atom position of current Atom." 236 self.atom.set_sigatm(sigatm_array)
237
238 - def get_structure(self):
239 "Return the structure." 240 # first sort everything 241 # self.structure.sort() 242 # Add the header dict 243 self.structure.header=self.header 244 return self.structure
245
246 - def set_symmetry(self, spacegroup, cell):
247 pass
248