예제 #1
0
    def run(self):
        # creating the atom group
        _acidic = self.u.select_atoms(self.sel_acidic)
        _basic = self.u.select_atoms(self.sel_basic)
        #defining the matrix
        _salt_bridge = np.zeros((self.nres, self.nres), int)

        for ts in self.u.trajectory[self.start:self.stop:self.stride]:
            _dists = capped_distance(_acidic.positions, _basic.positions,
                                     max_cutoff=self.sb_cutoff,
                                     return_distances=False,
                                     box=_acidic.dimensions)
            # At least for salt bridges, we need only that one bridge is formed.
            # Therefore we will map the pairs of atoms indices into the pairs of
            # residues and take the unique pair to compose the matrix.
            # It is symmetric, but we can use the upper diagonal part.
            _residxs = []
            for resAcid, resBasic in zip(_acidic[_dists[:, 0]].resindices, _basic[_dists[:, 1]].resindices):
                _residxs.append([resAcid, resBasic])
            _residxs = np.unique(np.array(_residxs), axis=0)  # shifting back
            for r in _residxs:
                _salt_bridge[r[0], r[1]] += 1

        SB_matrix = (_salt_bridge + _salt_bridge.T) * 100 / self.nframes
        np.savetxt(self.sb_file, SB_matrix)

        return SB_matrix
    def search(self, atoms, radius, level='A'):
        """
        Return all atoms/residues/segments that are within *radius* of the
        atoms in *atoms*.

        Parameters
        ----------
        atoms : AtomGroup, MDAnalysis.core.groups.Atom
          list of atoms
        radius : float
          Radius for search in Angstrom.
        level : str
          char (A, R, S). Return atoms(A), residues(R) or segments(S) within
          *radius* of *atoms*.
        """
        unique_idx = []
        if isinstance(atoms, Atom):
            positions = atoms.position.reshape(1, 3)
        else:
            positions = atoms.positions
        
        pairs = capped_distance(positions, self.atom_group.positions,
                                radius, box=self._box, return_distances=False)

        if pairs.size > 0:
            unique_idx = unique_int_1d(np.asarray(pairs[:, 1], dtype=np.int64))
        return self._index2level(unique_idx, level)
예제 #3
0
    def _unwrap_ns(self,
                   refset_cog,
                   configset_cog,
                   added,
                   to_be_added,
                   box,
                   method="pkdtree"):
        """
        Find NN in refset_cog and configset_cog and pass back
        the indices stored in added and to_be added.
        """
        distances = []
        dist = 8.0
        while len(distances) < 1:
            pairs, distances = capped_distance(
                refset_cog,
                configset_cog,
                dist,
                box=box,
                method=method,
                return_distances=True,
            )
            dist += 0.5

        minpair = np.where(distances == np.amin(distances))[0][0]

        imin = added[pairs[minpair][0]]
        jmin = to_be_added[pairs[minpair][1]]
        return imin, jmin
예제 #4
0
파일: core.py 프로젝트: htz1992213/mdgo
    def get_cluster_distance(
        self, run_start: int, run_end: int, neighbor_cutoff: float, cluster_center: str = "center"
    ) -> np.floating:
        """Calculates the average distance of the center of clusters/molecules

        Args:
            run_start: Start frame of analysis.
            run_end: End frame of analysis.
            neighbor_cutoff: Upper limit of first nearest neighbor.
            cluster_center: species name of cluster center. Default to "center".

        Return:
            The averaged distance.
        """
        center_atoms = self.wrapped_run.select_atoms(self.select_dict.get(cluster_center))
        trj = self.wrapped_run.trajectory[run_start:run_end:]
        means = []
        for ts in trj:
            distance_matrix = capped_distance(
                center_atoms.positions,
                center_atoms.positions,
                max_cutoff=neighbor_cutoff,
                box=ts.dimensions,
                return_distances=True,
            )[1]
            distance_matrix[distance_matrix == 0] = np.nan
            means.append(np.nanmean(distance_matrix))
        return np.mean(means)
예제 #5
0
    def _single_frame(self):

        pairs = capped_distance(self.membrane.positions,
                                self.membrane.positions,
                                max_cutoff=self.cutoff,
                                box=self._ts.dimensions,
                                return_distances=False)
        self.pairs = pairs

        # Find unique pairs of residues interacting
        # Currently we have pairs of atoms
        ref, neigh = np.unique(self._sorted_membrane_resindices[pairs],
                               axis=0).T

        # Dont keep self-interactions between lipids
        different = ref != neigh
        ref = ref[different]
        neigh = neigh[different]

        # store neighbours for this frame
        frame_start = self._frame_index * self.membrane.n_residues
        self.neighbours[ref, neigh + frame_start] = 1
        self.neighbours[
            neigh,
            ref + frame_start] = 1  # the neighbour matrix must be symmetric
예제 #6
0
 def _single_frame(self):
     
     pairs = capped_distance(
         self.membrane.positions,
         self.membrane.positions,
         max_cutoff=self.cutoff,
         box=self._ts.dimensions,
         return_distances=False
     )
     
     # Find unique pairs of residues interacting
     # Currently we have pairs of atoms
     ref, neigh = np.unique(self._sorted_membrane_resindices[pairs], axis=0).T
     
     # Dont keep self-interactions between lipids
     different = ref != neigh
     ref = ref[different]
     neigh = neigh[different]
     
     # store neighbours for this frame
     data = np.ones_like(ref)
     self.neighbours[self._frame_index] = scipy.sparse.csr_matrix(
         (data, (ref, neigh)),
         dtype=np.int8,
         shape=(self.membrane.n_residues, self.membrane.n_residues)
     )
예제 #7
0
파일: core.py 프로젝트: miaoliu/mdgo
    def get_cluster_distance(self, run_start, run_end, neighbor_cutoff,
                             cluster_center="center"):
        """ Calculates the average distance of the center of clusters/molecules

        Args:
            run_start (int): Start time step.
            run_end (int): End time step.
            neighbor_cutoff (int of float): Upper limit of
                first nearest neighbor.
            cluster_center (str): species name of cluster center.
                Default to "center".
        """
        center_atoms = (
            self.wrapped_run.select_atoms(self.select_dict.get(cluster_center))
        )
        trj = self.wrapped_run.trajectory[run_start:run_end:]
        means = []
        for ts in trj:
            distance_matrix = capped_distance(center_atoms.positions,
                                              center_atoms.positions,
                                              max_cutoff=neighbor_cutoff,
                                              box=ts.dimensions,
                                              return_distances=True)[1]
            distance_matrix[distance_matrix == 0] = np.nan
            means.append(np.nanmean(distance_matrix))
        return np.mean(means)
예제 #8
0
    def _single_frame(self, ts, atomgroups):
        u = atomgroups[0].universe

        box = ts.dimensions

        # Update donor-hydrogen pairs if necessary
        if self.update_selections:
            acceptors = u.select_atoms(self.acceptors_sel)
            donors, hydrogens = self._get_dh_pairs(u)
        else:
            acceptors = u.atoms[self._acceptors_ids]
            donors = u.atoms[self._donors_ids]
            hydrogens = u.atoms[self._hydrogens_ids]
        # find D and A within cutoff distance of one another
        # min_cutoff = 1.0 as an atom cannot form a hydrogen bond with itself
        d_a_indices, d_a_distances = capped_distance(
            donors.positions,
            acceptors.positions,
            max_cutoff=self.d_a_cutoff,
            min_cutoff=1.0,
            box=box,
            return_distances=True,
        )

        # Remove D-A pairs more than d_a_cutoff away from one another
        tmp_donors = donors[d_a_indices.T[0]]
        tmp_hydrogens = hydrogens[d_a_indices.T[0]]
        tmp_acceptors = acceptors[d_a_indices.T[1]]

        # Find D-H-A angles greater than d_h_a_angle_cutoff
        d_h_a_angles = np.rad2deg(
            calc_angles(
                tmp_donors.positions,
                tmp_hydrogens.positions,
                tmp_acceptors.positions,
                box=box
            )
        )
        hbond_indices = np.where(d_h_a_angles > self.d_h_a_angle)[0]

        # Retrieve atoms, distances and angles of hydrogen bonds
        hbond_donors = tmp_donors[hbond_indices]
        hbond_hydrogens = tmp_hydrogens[hbond_indices]
        hbond_acceptors = tmp_acceptors[hbond_indices]
        hbond_distances = d_a_distances[hbond_indices]
        hbond_angles = d_h_a_angles[hbond_indices]

        # Store data on hydrogen bonds found at this frame
        hbonds = [[], [], [], [], [], []]
        hbonds[0].extend(np.full_like(hbond_donors, ts.frame))
        hbonds[1].extend(hbond_donors.ids)
        hbonds[2].extend(hbond_hydrogens.ids)
        hbonds[3].extend(hbond_acceptors.ids)
        hbonds[4].extend(hbond_distances)
        hbonds[5].extend(hbond_angles)
        return np.asarray(hbonds).T
예제 #9
0
    def _single_frame(self):

        box = self._ts.dimensions

        # Update donor-hydrogen pairs if necessary
        if self.update_selections:
            self._donors, self._hydrogens = self._get_dh_pairs()

        # find D and A within cutoff distance of one another
        # min_cutoff = 1.0 as an atom cannot form a hydrogen bond with itself
        d_a_indices, d_a_distances = capped_distance(
            self._donors.positions,
            self._acceptors.positions,
            max_cutoff=self.d_a_cutoff,
            min_cutoff=1.0,
            box=box,
            return_distances=True,
        )

        # Remove D-A pairs more than d_a_cutoff away from one another
        tmp_donors = self._donors[d_a_indices.T[0]]
        tmp_hydrogens = self._hydrogens[d_a_indices.T[0]]
        tmp_acceptors = self._acceptors[d_a_indices.T[1]]

        # Find D-H-A angles greater than d_h_a_angle_cutoff
        d_h_a_angles = np.rad2deg(
            calc_angles(
                tmp_donors.positions,
                tmp_hydrogens.positions,
                tmp_acceptors.positions,
                box=box
            )
        )
        hbond_indices = np.where(d_h_a_angles > self.d_h_a_angle)[0]

        # Retrieve atoms, distances and angles of hydrogen bonds
        hbond_donors = tmp_donors[hbond_indices]
        hbond_hydrogens = tmp_hydrogens[hbond_indices]
        hbond_acceptors = tmp_acceptors[hbond_indices]
        hbond_distances = d_a_distances[hbond_indices]
        hbond_angles = d_h_a_angles[hbond_indices]

        # Store data on hydrogen bonds found at this frame
        self.hbonds[0].extend(np.full_like(hbond_donors, self._ts.frame))
        self.hbonds[1].extend(hbond_donors.indices)
        self.hbonds[2].extend(hbond_hydrogens.indices)
        self.hbonds[3].extend(hbond_acceptors.indices)
        self.hbonds[4].extend(hbond_distances)
        self.hbonds[5].extend(hbond_angles)
예제 #10
0
 def _single_frame(self):
     solute = self._solute[self._key]
     solvent = self._solvent[self._key]
     pairs, distances = capped_distance(solute.positions,
                                        solvent.positions,
                                        max(self._dists),
                                        box=self._ts.dimensions)
     solute_i, solvent_j = np.transpose(pairs)
     for d in self._dists:
         close_solv_atoms = solvent[solvent_j[distances < d]]
         result = [
             d, self._key[0], self._key[1], self._key[2], self._ts.time,
             close_solv_atoms.n_atoms
         ]
         for i in range(len(self._col)):
             self._res_dict[self._col[i]].append(result[i])
예제 #11
0
    def _single_frame(self, ts, atomgroups):
        g1, g2 = atomgroups
        u = g1.universe
        pairs, dist = distances.capped_distance(g1.positions,
                                                g2.positions,
                                                self._maxrange,
                                                box=u.dimensions)
        # If provided exclusions, create a mask of _result which
        # lets us take these out.
        if self._exclusion_block is not None:
            idxA = pairs[:, 0] // self._exclusion_block[0]
            idxB = pairs[:, 1] // self._exclusion_block[1]
            mask = np.where(idxA != idxB)[0]
            dist = dist[mask]
        count = np.histogram(dist, **self.rdf_settings)[0]
        volume = u.trajectory.ts.volume

        return np.array([count, np.array(volume, dtype=np.float64)])
예제 #12
0
    def _get_dh_pairs(self, u):
        """Finds donor-hydrogen pairs.

        Returns
        -------
        donors, hydrogens: AtomGroup, AtomGroup
            AtomGroups corresponding to all donors and all hydrogens.
            AtomGroups are ordered such that, if zipped, will produce a list
            of donor-hydrogen pairs.
        """

        # If donors_sel is not provided, use topology to find d-h pairs
        if not self.donors_sel:

            if not (hasattr(u, 'bonds') and len(u.bonds) != 0):
                raise ValueError(
                    'Cannot assign donor-hydrogen pairs via topology as no'
                    'bonded information is present. ',
                    'Please either: ',
                    'load a topology file with bonded information; ',
                    'use the guess_bonds() topology guesser; ',
                    'or set HydrogenBondAnalysis.donors_sel so that a '
                    'distance cutoff can be used.')

            hydrogens = u.select_atoms(self.hydrogens_sel)
            donors = sum(h.bonded_atoms[0] for h in hydrogens)

        # Otherwise, use d_h_cutoff as a cutoff distance
        else:

            hydrogens = u.select_atoms(self.hydrogens_sel)
            donors = u.select_atoms(self.donors_sel)
            donors_indices, hydrogen_indices = capped_distance(
                donors.positions,
                hydrogens.positions,
                max_cutoff=self.d_h_cutoff,
                box=u.dimensions,
                return_distances=False
            ).T

            donors = donors[donors_indices]
            hydrogens = hydrogens[hydrogen_indices]

        return donors, hydrogens
예제 #13
0
    def _get_dh_pairs(self):
        """Finds donor-hydrogen pairs.

        Returns
        -------
        donors, hydrogens: AtomGroup, AtomGroup
            AtomGroups corresponding to all donors and all hydrogens. AtomGroups are ordered such that, if zipped, will
            produce a list of donor-hydrogen pairs.
        """

        # If donors_sel is not provided, use topology to find d-h pairs
        if not self.donors_sel:

            # We're using u._topology.bonds rather than u.bonds as it is a million times faster to access.
            # This is because u.bonds also calculates properties of each bond (e.g bond length).
            # See https://github.com/MDAnalysis/mdanalysis/issues/2396#issuecomment-596251787
            if not (hasattr(self.u._topology, 'bonds')
                    and len(self.u._topology.bonds.values) != 0):
                raise NoDataError(
                    'Cannot assign donor-hydrogen pairs via topology as no bond information is present. '
                    'Please either: load a topology file with bond information; use the guess_bonds() '
                    'topology guesser; or set HydrogenBondAnalysis.donors_sel so that a distance cutoff '
                    'can be used.')

            hydrogens = self.u.select_atoms(self.hydrogens_sel)
            donors = sum(h.bonded_atoms[0] for h in hydrogens) if hydrogens \
                else AtomGroup([], self.u)

        # Otherwise, use d_h_cutoff as a cutoff distance
        else:

            hydrogens = self.u.select_atoms(self.hydrogens_sel)
            donors = self.u.select_atoms(self.donors_sel)
            donors_indices, hydrogen_indices = capped_distance(
                donors.positions,
                hydrogens.positions,
                max_cutoff=self.d_h_cutoff,
                box=self.u.dimensions,
                return_distances=False).T

            donors = donors[donors_indices]
            hydrogens = hydrogens[hydrogen_indices]

        return donors, hydrogens
예제 #14
0
    def _single_frame(self, ts, atomgroups):
        ags = [[atomgroups[2 * i], atomgroups[2 * i + 1]]
               for i in range(self.n)]
        count = [
            np.zeros((ag1.n_atoms, ag2.n_atoms, self.len), dtype=np.float64)
            for ag1, ag2 in ags
        ]
        for i, (ag1, ag2) in enumerate(ags):
            u = ag1.universe
            pairs, dist = distances.capped_distance(ag1.positions,
                                                    ag2.positions,
                                                    self._maxrange,
                                                    box=u.dimensions)

            for j, (idx1, idx2) in enumerate(pairs):
                count[i][idx1, idx2, :] = np.histogram(dist[j],
                                                       **self.rdf_settings)[0]

        volume = u.trajectory.ts.volume

        return np.array([np.array(count), np.array(volume, dtype=np.float64)])
예제 #15
0
    def _single_run(self, start, stop):
        """Perform a single pass of the trajectory"""
        self.u.trajectory[start]

        # Calculate partners at t=0
        box = self.u.dimensions if self.pbc else None

        # 2d array of all distances
        pair, d = capped_distance(self.h.positions,
                                  self.a.positions,
                                  max_cutoff=self.d_crit,
                                  box=box)
        if self.exclusions:
            # set to above dist crit to exclude
            exclude = np.column_stack((self.exclusions[0], self.exclusions[1]))
            pair = np.delete(pair, np.where(pair == exclude), 0)

        hidx, aidx = np.transpose(pair)

        a = calc_angles(self.d.positions[hidx],
                        self.h.positions[hidx],
                        self.a.positions[aidx],
                        box=box)
        # from amongst those, who also satisfiess angle crit
        idx2 = np.where(a > self.a_crit)
        hidx = hidx[idx2]
        aidx = aidx[idx2]

        nbonds = len(hidx)  # number of hbonds at t=0
        results = np.zeros_like(np.arange(start, stop, self._skip),
                                dtype=np.float32)

        if self.time_cut:
            # counter for time criteria
            count = np.zeros(nbonds, dtype=np.float64)

        for i, ts in enumerate(self.u.trajectory[start:stop:self._skip]):
            box = self.u.dimensions if self.pbc else None

            d = calc_bonds(self.h.positions[hidx],
                           self.a.positions[aidx],
                           box=box)
            a = calc_angles(self.d.positions[hidx],
                            self.h.positions[hidx],
                            self.a.positions[aidx],
                            box=box)

            winners = (d < self.d_crit) & (a > self.a_crit)
            results[i] = winners.sum()

            if self.bond_type == 'continuous':
                # Remove losers for continuous definition
                hidx = hidx[np.where(winners)]
                aidx = aidx[np.where(winners)]
            elif self.bond_type == 'intermittent':
                if self.time_cut:
                    # Add to counter of where losers are
                    count[~winners] += self._skip * self.u.trajectory.dt
                    count[winners] = 0  # Reset timer for winners

                    # Remove if you've lost too many times
                    # New arrays contain everything but removals
                    hidx = hidx[count < self.time_cut]
                    aidx = aidx[count < self.time_cut]
                    count = count[count < self.time_cut]
                else:
                    pass

            if len(hidx) == 0:  # Once everyone has lost, the fun stops
                break

        results /= nbonds

        return results
def contact_matrix(coord, cutoff=15.0, returntype="numpy", box=None):
    '''Calculates a matrix of contacts.

    There is a fast, high-memory-usage version for small systems
    (*returntype* = 'numpy'), and a slower, low-memory-usage version for
    larger systems (*returntype* = 'sparse').

    If *box* dimensions are passed then periodic boundary conditions
    are applied.

    Parameters
    ---------
    coord : array
       Array of coordinates of shape ``(N, 3)`` and dtype float32.
    cutoff : float, optional, default 15
       Particles within `cutoff` are considered to form a contact.
    returntype : string, optional, default "numpy"
       Select how the contact matrix is returned.
       * ``"numpy"``: return as an ``(N. N)`` :class:`numpy.ndarray`
       * ``"sparse"``: return as a :class:`scipy.sparse.lil_matrix`
    box : array-like or ``None``, optional, default ``None``
       Simulation cell dimensions in the form of
       :attr:`MDAnalysis.trajectory.base.Timestep.dimensions` when
       periodic boundary conditions should be taken into account for
       the calculation of contacts.

    Returns
    -------
    array or sparse matrix
       The contact matrix is returned in a format determined by the `returntype`
       keyword.

    See Also
    --------
    :mod:`MDAnalysis.analysis.contacts` for native contact analysis


    .. versionchanged:: 0.11.0
       Keyword *suppress_progmet* and *progress_meter_freq* were removed.
    '''

    if returntype == "numpy":
        adj = np.full((len(coord), len(coord)), False, dtype=bool)
        pairs = capped_distance(coord,
                                coord,
                                max_cutoff=cutoff,
                                box=box,
                                return_distances=False)

        idx, idy = np.transpose(pairs)
        adj[idx, idy] = True

        return adj
    elif returntype == "sparse":
        # Initialize square List of Lists matrix of dimensions equal to number
        # of coordinates passed
        sparse_contacts = scipy.sparse.lil_matrix((len(coord), len(coord)),
                                                  dtype='bool')
        if box is not None:
            # with PBC
            contact_matrix_pbc(coord, sparse_contacts, box, cutoff)
        else:
            # without PBC
            contact_matrix_no_pbc(coord, sparse_contacts, cutoff)
        return sparse_contacts
예제 #17
0
    def condensed_ions(
        self,
        cluster,
        headgroup,
        ion,
        distances,
        method="pkdtree",
        pbc=True,
        wrap=False,
    ):
        """
        Calculate number of species ion around each distance specified
        in distances around each cluster a cluster.
        MDAnalsys.lib.distances.capped_distances() is used for this,
        there is an issue with this code see this PR:
            https://github.com/MDAnalysis/mdanalysis/pull/2937
        as long as this is not fixed, I put pkdtree as standard method.

        Parameters
        ----------
        cluster: MDAnalysis.ResidueGroup
            cluster on which to perform analysis on.
        headgroup : str
            atom identifier of the headgroup, can also be a specific
            part of the headgroup or even a tailgroup.
        ion : str
            atom identifier of the species whose degree of condensation
            around the headgroups is to be determined.
        distances : float, list of floats
            Distance(s) up to which to determine the degree of
            condenstation. Can be multiple.
        method : {'bruteforce', 'nsgrid', 'pkdtree'}, optional
            Method to be passed to mda.lib.distances.capped_distance().
        pbc : bool, optional
            Wether or not to take pbc into account, by default True

        Returns:
        --------
        condensed_ions: list of ints
            the number of ions around headgroup for each distance.
        """
        condensed_ions = []
        self.universe = cluster.universe
        # Handle pbc
        # self._set_pbc_style(traj_pbc_style)
        if pbc:
            box = self.universe.dimensions
        else:
            box = None
        if wrap:
            UnwrapCluster().unwrap_cluster(cluster)

        # Define configuration set
        # This could be done with _select_species if refactored correctly.
        # Improvement: When looping over multiple distances do it first
        # for the largest distance, then adapt selection for shorter one.
        if isinstance(ion, str):
            ion = [ion]
        configset = self.universe.select_atoms("name {:s}".format(" ".join(ion)))
        configset = configset.atoms.positions
        # Define reference set
        if isinstance(headgroup, str):
            headgroup = [headgroup]
        refset = cluster.atoms.select_atoms("name {:s}".format(" ".join(headgroup)))
        refset = refset.atoms.positions

        condensed_ions = []
        for distance in distances:
            unique_idx = []
            # Call capped_distance for pairs
            pairs = capped_distance(
                refset,
                configset,
                distance,
                box=box,
                method=method,
                return_distances=False,
            )
            # Make unique
            if pairs.size > 0:
                unique_idx = unique_int_1d(np.asarray(pairs[:, 1], dtype=np.int64))
            condensed_ions.append(len(unique_idx))

        return condensed_ions