195 for ch
in self.
view.chains:
196 for r_idx, r
in enumerate(ch.residues):
197 r.SetIntProp(
"contact_idx", r_idx)
199 residue_lists = list()
207 min_chain_pos = list()
208 max_chain_pos = list()
211 ch = self.
view.FindChain(cname)
212 if ch.GetAtomCount() == 0:
213 raise RuntimeError(f
"Chain without atoms observed: \"{cname}\"")
214 residue_lists.append([r
for r
in ch.residues])
216 for r
in residue_lists[-1]:
217 pos = np.zeros((r.GetAtomCount(), 3))
218 for at_idx, at
in enumerate(r.atoms):
220 pos[(at_idx, 0)] = p[0]
221 pos[(at_idx, 1)] = p[1]
222 pos[(at_idx, 2)] = p[2]
224 min_res_pos = np.vstack([p.min(0)
for p
in res_pos])
225 max_res_pos = np.vstack([p.max(0)
for p
in res_pos])
226 min_res_x.append(min_res_pos[:, 0])
227 min_res_y.append(min_res_pos[:, 1])
228 min_res_z.append(min_res_pos[:, 2])
229 max_res_x.append(max_res_pos[:, 0])
230 max_res_y.append(max_res_pos[:, 1])
231 max_res_z.append(max_res_pos[:, 2])
232 min_chain_pos.append(min_res_pos.min(0))
233 max_chain_pos.append(max_res_pos.max(0))
234 per_res_pos.append(res_pos)
243 if np.max(min_chain_pos[ch1_idx] - max_chain_pos[ch2_idx]) > self.
contact_d:
245 if np.max(min_chain_pos[ch2_idx] - max_chain_pos[ch1_idx]) > self.
contact_d:
249 skip_one = np.subtract.outer(min_res_x[ch1_idx], max_res_x[ch2_idx]) > self.
contact_d
250 skip_one = np.logical_or(skip_one, np.subtract.outer(min_res_y[ch1_idx], max_res_y[ch2_idx]) > self.
contact_d)
251 skip_one = np.logical_or(skip_one, np.subtract.outer(min_res_z[ch1_idx], max_res_z[ch2_idx]) > self.
contact_d)
252 skip_two = np.subtract.outer(min_res_x[ch2_idx], max_res_x[ch1_idx]) > self.
contact_d
253 skip_two = np.logical_or(skip_two, np.subtract.outer(min_res_y[ch2_idx], max_res_y[ch1_idx]) > self.
contact_d)
254 skip_two = np.logical_or(skip_two, np.subtract.outer(min_res_z[ch2_idx], max_res_z[ch1_idx]) > self.
contact_d)
255 skip = np.logical_or(skip_one, skip_two.T)
258 r1_indices, r2_indices = np.nonzero(np.logical_not(skip))
259 ch1_per_res_pos = per_res_pos[ch1_idx]
260 ch2_per_res_pos = per_res_pos[ch2_idx]
261 for r1_idx, r2_idx
in zip(r1_indices, r2_indices):
263 p1 = ch1_per_res_pos[r1_idx]
264 p2 = ch2_per_res_pos[r2_idx]
265 x2 = np.sum(p1**2, axis=1)
266 y2 = np.sum(p2**2, axis=1)
267 xy = np.matmul(p1, p2.T)
268 x2 = x2.reshape(-1, 1)
269 squared_distances = x2 - 2*xy + y2
270 if np.min(squared_distances) <= scd:
272 r1 = residue_lists[ch1_idx][r1_idx]
273 r2 = residue_lists[ch2_idx][r2_idx]
277 self.
_contacts[cname_key].add((r1.GetIntProp(
"contact_idx"),
278 r2.GetIntProp(
"contact_idx")))
279 rnum1 = r1.GetNumber()
280 hr1 = f
"{self.chain_names[ch1_idx]}.{rnum1.num}.{rnum1.ins_code}"
281 rnum2 = r2.GetNumber()
282 hr2 = f
"{self.chain_names[ch2_idx]}.{rnum2.num}.{rnum2.ins_code}"
284 hr2.strip(
"\u0000")))