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