1
2
3
4
5
6 __doc__="""
7 Consumer class that builds a Structure object. This is used by
8 the PDBParser and MMCIFparser classes.
9 """
10
11 import warnings
12
13
14
15 from Structure import Structure
16 from Model import Model
17 from Chain import Chain
18 from Residue import Residue, DisorderedResidue
19 from Atom import Atom, DisorderedAtom
20
21 from PDBExceptions import PDBConstructionException, PDBConstructionWarning
22
23
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 """
30 self.line_counter=0
31 self.header={}
32
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
43
46
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
58 """Initiate a new Structure object with given id.
59
60 Arguments:
61 o id - string
62 """
63 self.structure=Structure(structure_id)
64
66 """Initiate a new Model object with given id.
67
68 Arguments:
69 o id - int
70 """
71 self.model=Model(model_id)
72 self.structure.add(self.model)
73
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 if __debug__:
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
91 """Flag a change in segid.
92
93 Arguments:
94 o segid - string
95 """
96 self.segid=segid
97
99 """
100 Initiate a new Residue object.
101
102 Arguments:
103 o resname - string, e.g. "ASN"
104 o field - hetero flag, "W" for waters, "H" for
105 hetero residues, otherwise blank.
106 o resseq - int, sequence identifier
107 o icode - string, insertion code
108 """
109 if field!=" ":
110 if field=="H":
111
112 field="H_"+resname
113 res_id=(field, resseq, icode)
114 if field==" ":
115 if self.chain.has_id(res_id):
116
117
118 if __debug__:
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
126
127 if duplicate_residue.disordered_has_id(resname):
128
129 self.residue=duplicate_residue
130 duplicate_residue.disordered_select(resname)
131 else:
132
133
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
140
141
142
143 if not self._is_completely_disordered(duplicate_residue):
144
145 self.residue=None
146 raise PDBConstructionException(\
147 "Blank altlocs in duplicate residue %s ('%s', %i, '%s')" \
148 % (resname, field, resseq, icode))
149 self.chain.detach_child(res_id)
150 new_residue=Residue(res_id, resname, self.segid)
151 disordered_residue=DisorderedResidue(res_id)
152 self.chain.add(disordered_residue)
153 disordered_residue.disordered_add(duplicate_residue)
154 disordered_residue.disordered_add(new_residue)
155 self.residue=disordered_residue
156 return
157 residue=Residue(res_id, resname, self.segid)
158 self.chain.add(residue)
159 self.residue=residue
160
161 - def init_atom(self, name, coord, b_factor, occupancy, altloc, fullname,
162 serial_number=None, element=None):
163 """
164 Initiate a new Atom object.
165
166 Arguments:
167 o name - string, atom name, e.g. CA, spaces should be stripped
168 o coord - Numeric array (Float0, size 3), atomic coordinates
169 o b_factor - float, B factor
170 o occupancy - float
171 o altloc - string, alternative location specifier
172 o fullname - string, atom name including spaces, e.g. " CA "
173 o element - string, upper case, e.g. "HG" for mercury
174 """
175 residue=self.residue
176
177
178 if residue is None:
179 return
180
181
182
183
184
185 if residue.has_id(name):
186 duplicate_atom=residue[name]
187
188 duplicate_fullname=duplicate_atom.get_fullname()
189 if duplicate_fullname!=fullname:
190
191 name=fullname
192 if __debug__:
193 warnings.warn("WARNING: atom names %s and %s differ "
194 "only in spaces at line %i."
195 % (duplicate_fullname, fullname,
196 self.line_counter),
197 PDBConstructionWarning)
198 atom=self.atom=Atom(name, coord, b_factor, occupancy, altloc,
199 fullname, serial_number, element)
200 if altloc!=" ":
201
202 if residue.has_id(name):
203
204 duplicate_atom=residue[name]
205 if duplicate_atom.is_disordered()==2:
206 duplicate_atom.disordered_add(atom)
207 else:
208
209
210
211
212
213 residue.detach_child(name)
214 disordered_atom=DisorderedAtom(name)
215 residue.add(disordered_atom)
216 disordered_atom.disordered_add(atom)
217 disordered_atom.disordered_add(duplicate_atom)
218 residue.flag_disordered()
219 if __debug__:
220 warnings.warn("WARNING: disordered atom found "
221 "with blank altloc before line %i.\n"
222 % self.line_counter,
223 PDBConstructionWarning)
224 else:
225
226
227 disordered_atom=DisorderedAtom(name)
228 residue.add(disordered_atom)
229
230
231 disordered_atom.disordered_add(atom)
232 residue.flag_disordered()
233 else:
234
235 residue.add(atom)
236
238 "Set anisotropic B factor of current Atom."
239 self.atom.set_anisou(anisou_array)
240
242 "Set standard deviation of anisotropic B factor of current Atom."
243 self.atom.set_siguij(siguij_array)
244
246 "Set standard deviation of atom position of current Atom."
247 self.atom.set_sigatm(sigatm_array)
248
256
259