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, serial_number=None):
162 """
163 Initiate a new Atom object.
164
165 Arguments:
166 o name - string, atom name, e.g. CA, spaces should be stripped
167 o coord - Numeric array (Float0, size 3), atomic coordinates
168 o b_factor - float, B factor
169 o occupancy - float
170 o altloc - string, alternative location specifier
171 o fullname - string, atom name including spaces, e.g. " CA "
172 """
173 residue=self.residue
174
175
176 if residue is None:
177 return
178
179
180
181
182
183 if residue.has_id(name):
184 duplicate_atom=residue[name]
185
186 duplicate_fullname=duplicate_atom.get_fullname()
187 if duplicate_fullname!=fullname:
188
189 name=fullname
190 if __debug__:
191 warnings.warn("WARNING: atom names %s and %s differ "
192 "only in spaces at line %i."
193 % (duplicate_fullname, fullname,
194 self.line_counter),
195 PDBConstructionWarning)
196 atom=self.atom=Atom(name, coord, b_factor, occupancy, altloc, fullname, serial_number)
197 if altloc!=" ":
198
199 if residue.has_id(name):
200
201 duplicate_atom=residue[name]
202 if duplicate_atom.is_disordered()==2:
203 duplicate_atom.disordered_add(atom)
204 else:
205
206
207
208
209
210 residue.detach_child(name)
211 disordered_atom=DisorderedAtom(name)
212 residue.add(disordered_atom)
213 disordered_atom.disordered_add(atom)
214 disordered_atom.disordered_add(duplicate_atom)
215 residue.flag_disordered()
216 if __debug__:
217 warnings.warn("WARNING: disordered atom found "
218 "with blank altloc before line %i.\n"
219 % self.line_counter,
220 PDBConstructionWarning)
221 else:
222
223
224 disordered_atom=DisorderedAtom(name)
225 residue.add(disordered_atom)
226
227
228 disordered_atom.disordered_add(atom)
229 residue.flag_disordered()
230 else:
231
232 residue.add(atom)
233
235 "Set anisotropic B factor of current Atom."
236 self.atom.set_anisou(anisou_array)
237
239 "Set standard deviation of anisotropic B factor of current Atom."
240 self.atom.set_siguij(siguij_array)
241
243 "Set standard deviation of atom position of current Atom."
244 self.atom.set_sigatm(sigatm_array)
245
253
256