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