def _get_other(self, central_xyz: ArrayLike, other: ArrayLike, box: Optional[ArrayLike]=None) -> Optional[ArrayLike]: pairs2 = capped_distance(central_xyz, other, self.cutoff_other, box=box, return_distances=False) if len(pairs2): other_xyz = other[np.unique(pairs2[:, 1])] else: other_xyz = None return other_xyz
def _single_frame(self): pairs = capped_distance(self.protein.positions, self.group.positions, self.cutoff, box=self.universe.dimensions, return_distances=False) prot = self.protein_rix[pairs[:, 0]] group = self.group_rix[pairs[:, 1]] tmp = np.zeros_like(self.percent_contact) tmp[(prot, group)] = 1 self.percent_contact += tmp
def get_distances_with_projection(coordinates: ArrayLike, orientations: ArrayLike, cutoff: float, box: Optional[ArrayLike] = None, angle_factor: float = 1) -> ArrayLike: n_coordinates = len(coordinates) # set up distance matrix filler = (angle_factor + 1) * cutoff dist_mat = np.ones((n_coordinates, n_coordinates)) * filler dist_mat[np.diag_indices(n_coordinates)] = 0 pairs, dists = capped_distance(coordinates, coordinates, cutoff, box=box, return_distances=True) pi, pj = tuple(pairs.T) # split pairs and distances by residue splix = np.where(np.ediff1d(pairs[:, 0]))[0] + 1 plist = np.split(pairs, splix) dlist = np.split(dists, splix) # project distances onto orientation vector for p, d in zip(plist, dlist): i = p[0, 0] js = p[1:, 1] # first is self-to-self d = d[1:] i_coord = coordinates[i] # TODO: can I get around this? slow neigh_ = coordinates[js].copy() if box is not None: unwrap_around(neigh_, i_coord, box[:3]) neigh_ -= i_coord vec = orientations[[i]] if np.any(np.isnan(vec)): continue ang_ = calc_cosine_similarity(vec, neigh_) proj = np.abs(d * ang_) # weight projected distance by angle_factor half = (proj * angle_factor)[0] dist_mat[i, js] = half + d dist_mat += dist_mat.T # symmetrize dist_mat /= 2 return dist_mat
def _update_leaflets(self): """Update the ``residue_leaflets`` attribute for the current frame.""" self.leafletfinder.run() self.leaflet_atomgroups = {} # assign inner residues inside_rix = self.residues_inside.resindices for rix in inside_rix: i = self._resindex_to_analysis_order[rix] lf = self.leafletfinder.resindex_to_leaflet[rix] self.residue_leaflets[i] = lf if not self._first_atoms_outside: return # assign outside residues by neighbors box = self.get_box() pairs = capped_distance(self._first_atoms_outside.positions, self.leafletfinder._first_atoms.positions, max_cutoff=self.leafletfinder.cutoff, box=box, return_distances=False) splix = np.where(np.ediff1d(pairs[:, 0]))[0] + 1 plist = np.split(pairs, splix) outside_rix = self.residues_outside.resindices for arr in plist: i = self._resindex_to_analysis_order[outside_rix[arr[0, 0]]] neighbor_rix = self.leafletfinder.residues.resindices[arr[:, 1]] # neighbor_ix = np.array([self._resindex_to_analysis_order[j] # for j in neighbor_rix]) # get most common neighbors leaflet_is = [ self.leafletfinder.resindex_to_leaflet[r] for r in neighbor_rix ] most_common = np.bincount(leaflet_is).argmax() self.residue_leaflets[i] = most_common self.leaflet_residues = { i: list() for i in np.unique(self.residue_leaflets) } for i, lf_i in enumerate(self.residue_leaflets): self.leaflet_residues[lf_i].append(i) for lf_i, res_i in self.leaflet_residues.items(): ag = sum(self.sel_by_residue[i] for i in res_i) self.leaflet_atomgroups[lf_i] = ag
def _single_frame(self): other = self.other.positions box = self.get_box() for lf_i in range(self.n_leaflets): ag = self.leaflet_atomgroups[lf_i] coords = get_centers_by_residue(ag) pairs, dists = capped_distance(coords, coords, self.cutoff, box=box, return_distances=True) if not len(pairs): continue # think this is faster than constructing massive voronoi diagram splix = np.where(np.ediff1d(pairs[:, 0]))[0] + 1 plist = np.split(pairs, splix) dlist = np.split(dists, splix) d_order = [np.argsort(x) for x in dlist] plist = [p[x[:self.max_neighbors+1]] for p, x in zip(plist, d_order)] for pairs_ in plist: central_i = pairs_[0, 0] central_coord = coords[central_i] neighbor_coords = coords[pairs_[1:, 1]] other_coords = self._get_other_coordinates(central_coord, other, box) try: area = lipid_area(central_coord, neighbor_coords, other_coordinates=other_coords, box=box) except ValueError: area = np.nan resindex = ag.residues[central_i].resindex residue_index = self._resindex_to_analysis_order[resindex] residue_label = self.ids[residue_index] self.areas[self._frame_index][residue_index] = area self.areas_by_leaflet[self._frame_index][lf_i][residue_index] = area self.areas_by_attr[lf_i][residue_label].append(area)
def _get_capped_distances(self, atomgroup: AtomGroup) -> ArrayLike: return capped_distance(self._first_atoms.positions, atomgroup.positions, box=self.get_box(), max_cutoff=self.cutoff, return_distances=False)
def _single_frame(self): # initial scoop for nearby groups coords_ = self.selection.positions pairs = distances.capped_distance(self.protein.positions, coords_, self.cutoff, box=self.protein.dimensions, return_distances=False) if pairs.size > 0: indices = np.unique(pairs[:, 1]) else: indices = [] # now look for groups in the buffer if len(indices) and self.buffer: pairs2, dist = distances.capped_distance( self.protein.positions, coords_, self.max_cutoff, min_cutoff=self.cutoff, box=self.protein.dimensions, return_distances=True) # don't count things in inner cutoff mask = [x not in indices for x in pairs2[:, 1]] pairs2 = pairs2[mask] dist = dist[mask] if pairs2.size > 0: _ix = np.argsort(pairs2[:, 1]) indices2 = pairs2[_ix][:, 1] dist = dist[_ix] - self.cutoff init_resix2 = self.selection.resindices[indices2] # sort through for minimum distance ids2, splix = np.unique(init_resix2, return_index=True) resix2 = init_resix2[splix] split_dist = np.split(dist, splix[1:]) min_dist = np.array([x.min() for x in split_dist]) # logistic function for i, leaflet_residues in self._current_leaflet_residues.items( ): ids = self._current_leaflet_ids[i] match, rix, lix = np.intersect1d( resix2, leaflet_residues.resindices, assume_unique=True, return_indices=True) subdist = min_dist[rix] subids = ids[lix] for j, x in enumerate(self.ids): mask = (subids == x) xdist = subdist[mask] exp = -0.5 * ((xdist / self._buffer_sigma)**2) n = self._buffer_coeff * np.exp(exp) self.near_counts[i, j, self._frame_index] += n.sum() soft = self.near_counts[:, :, self._frame_index].sum() init_resix = self.selection.resindices[indices] resix = np.unique(init_resix) for i, leaflet_residues in self._current_leaflet_residues.items(): ids = self._current_leaflet_ids[i] _, ix1, ix2 = np.intersect1d(resix, leaflet_residues.resindices, assume_unique=True, return_indices=True) self.total_counts[i, self._frame_index] = len(ix1) subids = ids[ix2] for j, x in enumerate(self.ids): self.residue_counts[i, j, self._frame_index] += sum(ids == x) self.near_counts[i, j, self._frame_index] += sum(subids == x) both = self.near_counts[:, :, self._frame_index].sum()