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   
24 -class StructureBuilder(object):
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, serial_num=None):
66 """Initiate a new Model object with given id. 67 68 Arguments: 69 o id - int 70 o serial_num - int 71 """ 72 self.model = Model(model_id, serial_num) 73 self.structure.add(self.model)
74
75 - def init_chain(self, chain_id):
76 """Initiate a new Chain object with given id. 77 78 Arguments: 79 o chain_id - string 80 """ 81 if self.model.has_id(chain_id): 82 self.chain = self.model[chain_id] 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 104 - resname - string, e.g. "ASN" 105 - field - hetero flag, "W" for waters, "H" for 106 hetero residues, otherwise blank. 107 - resseq - int, sequence identifier 108 - 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 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 if resname == duplicate_residue.resname: 140 warnings.warn("WARNING: Residue ('%s', %i, '%s','%s')" 141 " already defined with the same name at line %i." 142 % (field, resseq, icode, resname, self.line_counter), 143 PDBConstructionWarning) 144 self.residue = duplicate_residue 145 return 146 # Make a new DisorderedResidue object and put all 147 # the Residue objects with the id (field, resseq, icode) in it. 148 # These residues each should have non-blank altlocs for all their atoms. 149 # If not, the PDB file probably contains an error. 150 if not self._is_completely_disordered(duplicate_residue): 151 # if this exception is ignored, a residue will be missing 152 self.residue = None 153 raise PDBConstructionException( 154 "Blank altlocs in duplicate residue %s ('%s', %i, '%s')" 155 % (resname, field, resseq, icode)) 156 self.chain.detach_child(res_id) 157 new_residue = Residue(res_id, resname, self.segid) 158 disordered_residue = DisorderedResidue(res_id) 159 self.chain.add(disordered_residue) 160 disordered_residue.disordered_add(duplicate_residue) 161 disordered_residue.disordered_add(new_residue) 162 self.residue = disordered_residue 163 return 164 self.residue = Residue(res_id, resname, self.segid) 165 self.chain.add(self.residue)
166
167 - def init_atom(self, name, coord, b_factor, occupancy, altloc, fullname, 168 serial_number=None, element=None):
169 """ 170 Initiate a new Atom object. 171 172 Arguments: 173 o name - string, atom name, e.g. CA, spaces should be stripped 174 o coord - Numeric array (Float0, size 3), atomic coordinates 175 o b_factor - float, B factor 176 o occupancy - float 177 o altloc - string, alternative location specifier 178 o fullname - string, atom name including spaces, e.g. " CA " 179 o element - string, upper case, e.g. "HG" for mercury 180 """ 181 residue = self.residue 182 # if residue is None, an exception was generated during 183 # the construction of the residue 184 if residue is None: 185 return 186 # First check if this atom is already present in the residue. 187 # If it is, it might be due to the fact that the two atoms have atom 188 # names that differ only in spaces (e.g. "CA.." and ".CA.", 189 # where the dots are spaces). If that is so, use all spaces 190 # in the atom name of the current atom. 191 if residue.has_id(name): 192 duplicate_atom = residue[name] 193 # atom name with spaces of duplicate atom 194 duplicate_fullname = duplicate_atom.get_fullname() 195 if duplicate_fullname != fullname: 196 # name of current atom now includes spaces 197 name = fullname 198 warnings.warn("Atom names %r and %r differ " 199 "only in spaces at line %i." 200 % (duplicate_fullname, fullname, 201 self.line_counter), 202 PDBConstructionWarning) 203 self.atom = Atom(name, coord, b_factor, occupancy, altloc, 204 fullname, serial_number, element) 205 if altloc != " ": 206 # The atom is disordered 207 if residue.has_id(name): 208 # Residue already contains this atom 209 duplicate_atom = residue[name] 210 if duplicate_atom.is_disordered() == 2: 211 duplicate_atom.disordered_add(self.atom) 212 else: 213 # This is an error in the PDB file: 214 # a disordered atom is found with a blank altloc 215 # Detach the duplicate atom, and put it in a 216 # DisorderedAtom object together with the current 217 # atom. 218 residue.detach_child(name) 219 disordered_atom = DisorderedAtom(name) 220 residue.add(disordered_atom) 221 disordered_atom.disordered_add(self.atom) 222 disordered_atom.disordered_add(duplicate_atom) 223 residue.flag_disordered() 224 warnings.warn("WARNING: disordered atom found " 225 "with blank altloc before line %i.\n" 226 % self.line_counter, 227 PDBConstructionWarning) 228 else: 229 # The residue does not contain this disordered atom 230 # so we create a new one. 231 disordered_atom = DisorderedAtom(name) 232 residue.add(disordered_atom) 233 # Add the real atom to the disordered atom, and the 234 # disordered atom to the residue 235 disordered_atom.disordered_add(self.atom) 236 residue.flag_disordered() 237 else: 238 # The atom is not disordered 239 residue.add(self.atom)
240
241 - def set_anisou(self, anisou_array):
242 "Set anisotropic B factor of current Atom." 243 self.atom.set_anisou(anisou_array)
244
245 - def set_siguij(self, siguij_array):
246 "Set standard deviation of anisotropic B factor of current Atom." 247 self.atom.set_siguij(siguij_array)
248
249 - def set_sigatm(self, sigatm_array):
250 "Set standard deviation of atom position of current Atom." 251 self.atom.set_sigatm(sigatm_array)
252
253 - def get_structure(self):
254 "Return the structure." 255 # first sort everything 256 # self.structure.sort() 257 # Add the header dict 258 self.structure.header = self.header 259 return self.structure
260
261 - def set_symmetry(self, spacegroup, cell):
262 pass
263