Beispiel #1
0
 def _update_selection_1(self):
     self._s1 = self.u.select_atoms(self.selection1)
     self._s2 = self.u.select_atoms(self.selection2)
     if self.filter_first and self._s1:
         self.logger_debug('Size of selection 1 before filtering:'
                           ' {} atoms'.format(len(self._s1)))
         ns_selection_1 = AtomNeighborSearch(self._s1)
         self._s1 = ns_selection_1.search(self._s2, 3. * self.distance)
     self.logger_debug("Size of selection 1: {0} atoms".format(len(self._s1)))
     self._s1_donors = {}
     self._s1_donors_h = {}
     self._s1_acceptors = {}
     if self.selection1_type in ('donor', 'both'):
         self._s1_donors = self._s1.select_atoms(
             'name {0}'.format(' '.join(self.donors)))
         self._s1_donors_h = {}
         for i, d in enumerate(self._s1_donors):
             tmp = self._get_bonded_hydrogens(d)
             if tmp:
                 self._s1_donors_h[i] = tmp
         self.logger_debug("Selection 1 donors: {0}".format(len(self._s1_donors)))
         self.logger_debug("Selection 1 donor hydrogens: {0}".format(len(self._s1_donors_h)))
     if self.selection1_type in ('acceptor', 'both'):
         self._s1_acceptors = self._s1.select_atoms(
             'name {0}'.format(' '.join(self.acceptors)))
         self.logger_debug("Selection 1 acceptors: {0}".format(len(self._s1_acceptors)))
Beispiel #2
0
    def _update_water_selection(self):
        self._water = self.u.select_atoms(self.water_selection)
        self.logger_debug('Size of water selection before filtering:'
                          ' {} atoms'.format(len(self._water)))
        if self.filter_first:
            ns_water_selection = AtomNeighborSearch(self._water)
            self._water = ns_water_selection.search(self._s1,
                                                    3. * self.distance)
            self._water = ns_water_selection.search(self._s2,
                                                    3. * self.distance)

        self.logger_debug("Size of water selection: {0} atoms".format(len(self._water)))
        self._water_donors = {}
        self._water_donors_h = {}
        self._water_acceptors = {}
        if not self._water:
            logger.warning("Water selection '{0}' did not select any atoms."
                           .format(str(self.water_selection)[:80]))
        else:
            self._water_donors = self._water.select_atoms(
                'name {0}'.format(' '.join(self.donors)))
            self._water_donors_h = {}
            for i, d in enumerate(self._water_donors):
                tmp = self._get_bonded_hydrogens(d)
                if tmp:
                    self._water_donors_h[i] = tmp
            self.logger_debug("Water donors: {0}".format(len(self._water_donors)))
            self.logger_debug("Water donor hydrogens: {0}".format(len(self._water_donors_h)))
            self._water_acceptors = self._water.select_atoms(
                'name {0}'.format(' '.join(self.acceptors)))
            self.logger_debug("Water acceptors: {0}".format(len(self._water_acceptors)))
Beispiel #3
0
def get_hist(structure,
             trajectory,
             start=0,
             stop=-1,
             step=1,
             contact_sel="name PO1 PO2"):
    u = mda.Universe(structure, trajectory)
    protein = u.select_atoms("name BB SC1 SC2 SC3 SC4")
    contact_group = u.select_atoms(contact_sel)
    resname_hist = {}
    for frame in u.trajectory[start:stop:step]:
        tree = AtomNeighborSearch(protein, box=u.dimensions)
        for atom in contact_group:
            near = tree.search(atom, 6., level='R')
            if len(near) == 0:
                #print(near)
                continue
            else:
                resids = [x.resid for x in near]
                for resid in resids:
                    if resid in resname_hist:
                        resname_hist[resid] += 1
                    else:
                        resname_hist[resid] = 1
    resname_hist = OrderedDict(sorted(resname_hist.items()))
    return resname_hist
Beispiel #4
0
    def define_residues_for_plotting_topology(self, cutoff):
        """
        This function defines the residues for plotting in case only a topology file has been submitted.
        In this case the residence time analysis in not necessary and it is enough just to find all
        residues within a cutoff distance.
            Takes:
                * cutoff * - cutoff distance in angstroms that defines native contacts
            Output:
                *
        """

        #self.protein_selection = self.universe.select_atoms('all and around '+str(cutoff)+' (segid '+str(self.universe.ligand.segids[0])+' and resid '+str(self.universe.ligand.resids[0])+')')
        #The previous line was not working on some examples for some reason - switch to more efficient Neighbour Search
        n = AtomNeighborSearch(
            self.universe.select_atoms('protein and not name H* or (segid ' +
                                       str(self.universe.ligand.segids[0]) +
                                       ' and resid ' +
                                       str(self.universe.ligand.resids[0]) +
                                       ')'),
            bucket_size=10)
        self.protein_selection = n.search(self.universe.ligand,
                                          cutoff,
                                          level="A")
        for atom in self.protein_selection.atoms:
            #for non-analysis plots
            residue = (atom.resname, str(atom.resid), atom.segid)
            if residue not in self.dict_of_plotted_res.keys(
            ) and atom not in self.universe.ligand.atoms:
                self.dict_of_plotted_res[residue] = [1]
        assert len(
            self.dict_of_plotted_res
        ) != 0, "Nothing to draw for this ligand (residue number: " + self.universe.ligand.resids[
            0] + " on the chain " + self.universe.ligand.segids[
                0] + ") - check the position of your ligand within the topology file."
Beispiel #5
0
    def test_neighborhood(self):
        '''test KDTree-based distance search around query atoms

        Creates a KDTree of the protein and uses the coordinates of
        the atoms in the query pdb to create a list of protein
        residues within 4.0A of the query atoms.
        '''
        protein = self.universe.select_atoms("protein")
        ns_protein = AtomNeighborSearch(protein)
        query_atoms = self.query_universe.atoms
        residue_neighbors = ns_protein.search(query_atoms, 4.0)
        assert_equal(len(residue_neighbors), 80)
Beispiel #6
0
    def test_neighborhood(self):
        '''test KDTree-based distance search around query atoms

        Creates a KDTree of the protein and uses the coordinates of
        the atoms in the query pdb to create a list of protein
        residues within 4.0A of the query atoms.
        '''
        protein = self.universe.select_atoms("protein")
        ns_protein = AtomNeighborSearch(protein)
        query_atoms = self.query_universe.atoms
        residue_neighbors = ns_protein.search(query_atoms, 4.0)
        assert_equal(len(residue_neighbors), 80)
Beispiel #7
0
def interdomain_interactions(domain1, domain2, frame_number):
    """Calculate interactions between domain1 and domain2 present in the given frame

    Parameters
    ----------
    domain1: MDAnalysis.core.groups.AtomGroup
        Atoms comprising the first domain
    domain2: MDAnalysis.core.groups.AtomGroup
        Atoms comprising the second domain
    frame_number: int
        Frame number, numbering consistent with the original trajectory (for output)

    Returns
    -------
    domain_interactions: list
        List contaning frame number, residue number, electrostatic, van der Waals and total interaction energy. This
        list is subsequently printed to output.
    """

    possible_neighbors = AtomNeighborSearch(
        domain2.select_atoms('not resname WAT', updating=True))
    domain_interactions = list()
    calculate_vdw = load_from_config('parameters', 'vdw')[0] == 'True'
    for residue in domain1.residues:
        if residue.resname != 'WAT' and residue.resname != 'SOL':
            neighbor_atoms = possible_neighbors.search(
                residue.atoms,
                float(load_from_config('parameters', 'cutoff')[0]),
                level='A')
            eelec = 0
            evdw = 0
            for residue_atom in residue.atoms:
                for neighbor_atom in neighbor_atoms:
                    eelec += electrostatic_energy(residue_atom, neighbor_atom,
                                                  domain1.dimensions)
                    if calculate_vdw:
                        evdw += vdw_energy(residue_atom, neighbor_atom,
                                           domain1.dimensions)
            domain_interactions.append(
                '{:<10d} {:<10d} {:>10.5f} {:>10.5f} {:>10.5f}'.format(
                    frame_number, residue.resid, eelec, evdw, eelec + evdw))
    return domain_interactions
Beispiel #8
0
    def define_residues_for_plotting_topology(self,cutoff):
        """
        This function defines the residues for plotting in case only a topology file has been submitted.
        In this case the residence time analysis in not necessary and it is enough just to find all
        residues within a cutoff distance.
            Takes:
                * cutoff * - cutoff distance in angstroms that defines native contacts
            Output:
                *
        """

        #self.protein_selection = self.universe.select_atoms('all and around '+str(cutoff)+' (segid '+str(self.universe.ligand.segids[0])+' and resid '+str(self.universe.ligand.resids[0])+')')
        #The previous line was not working on some examples for some reason - switch to more efficient Neighbour Search
        n = AtomNeighborSearch(self.universe.select_atoms('protein and not name H* or (segid '+str(self.universe.ligand.segids[0])+' and resid '+str(self.universe.ligand.resids[0])+')'), bucket_size=10)
        self.protein_selection = n.search(self.universe.ligand,cutoff,level="A")
        for atom in self.protein_selection.atoms:
                #for non-analysis plots
                residue = (atom.resname, str(atom.resid), atom.segid)
                if residue not in self.dict_of_plotted_res.keys() and atom not in self.universe.ligand.atoms:
                    self.dict_of_plotted_res[residue]=[1]
        assert len(self.dict_of_plotted_res)!=0, "Nothing to draw for this ligand (residue number: "+ self.universe.ligand.resids[0] +" on the chain "+ self.universe.ligand.segids[0] +") - check the position of your ligand within the topology file."
Beispiel #9
0
def between(group, A, B, distance):
    """Return sub group of `group` that is within `distance` of both `A` and `B`

    This function is not aware of periodic boundary conditions.

    Can be used to find bridging waters or molecules in an interface.

    Similar to "*group* and (AROUND *A* *distance* and AROUND *B* *distance*)".

    Parameters
    ----------
    group : AtomGroup
        Find members of `group` that are between `A` and `B`
    A : AtomGroup
    B : AtomGroup
        `A` and `B` are the groups of atoms between which atoms in
        `group` are searched for.  The function works is more
        efficient if `group` is bigger than either `A` or `B`.
    distance : float
        maximum distance for an atom to be counted as in the vicinity of
        `A` or `B`

    Returns
    -------
    AtomGroup
        :class:`~MDAnalysis.core.groups.AtomGroup` of atoms that
        fulfill the criterion


    .. versionadded: 0.7.5

    """
    ns_group = AtomNeighborSearch(group)
    resA = set(ns_group.search(A, distance))
    resB = set(ns_group.search(B, distance))
    return sum(sorted(resB.intersection(resA)))
Beispiel #10
0
def between(group, A, B, distance):
    """Return sub group of `group` that is within `distance` of both `A` and `B`

    This function is not aware of periodic boundary conditions.

    Can be used to find bridging waters or molecules in an interface.

    Similar to "*group* and (AROUND *A* *distance* and AROUND *B* *distance*)".

    Parameters
    ----------
    group : AtomGroup
        Find members of `group` that are between `A` and `B`
    A : AtomGroup
    B : AtomGroup
        `A` and `B` are the groups of atoms between which atoms in
        `group` are searched for.  The function works is more
        efficient if `group` is bigger than either `A` or `B`.
    distance : float
        maximum distance for an atom to be counted as in the vicinity of
        `A` or `B`

    Returns
    -------
    AtomGroup
        :class:`~MDAnalysis.core.groups.AtomGroup` of atoms that
        fulfill the criterion


    .. versionadded: 0.7.5

    """
    ns_group = AtomNeighborSearch(group)
    resA = set(ns_group.search(A, distance))
    resB = set(ns_group.search(B, distance))
    return sum(sorted(resB.intersection(resA)))
Beispiel #11
0
def get_cluster_list(aggregate_species, cutoff=7.5):
    """Get Cluster from single frame

    """  
    from MDAnalysis.lib.NeighborSearch import AtomNeighborSearch

    cluster_list = []
    aggregate_species_dict = aggregate_species.groupby("resids")
    
    for atoms in aggregate_species_dict.values():
        cluster_temp = set(AtomNeighborSearch(aggregate_species).search(
                                                atoms=atoms, 
                                                radius=cutoff, 
                                                level="R"
                                                ))
        
        cluster_list = merge_cluster(cluster_list, cluster_temp)   
        
    return cluster_list
Beispiel #12
0
    def run(self, start=None, stop=None, step=None, verbose=None, debug=None):
        """Analyze trajectory and produce timeseries.

        Stores the water bridge data per frame as
        :attr:`WaterBridgeAnalysis.timeseries` (see there for output
        format).

        Parameters
        ----------
        start : int (optional)
            starting frame-index for analysis, ``None`` is the first one, 0.
            `start` and `stop` are 0-based frame indices and are used to slice
            the trajectory (if supported) [``None``]
        stop : int (optional)
            last trajectory frame for analysis, ``None`` is the last one
            [``None``]
        step : int (optional)
            read every `step` between `start` (included) and `stop` (excluded),
            ``None`` selects 1. [``None``]
        verbose : bool (optional)
             toggle progress meter output
             :class:`~MDAnalysis.lib.log.ProgressMeter` [``True``]
        debug : bool (optional)
             enable detailed logging of debugging information; this can create
             *very big* log files so it is disabled (``False``) by default;
             setting `debug` toggles the debug status for
             :class:`WaterBridgeAnalysis`, namely the value of
             :attr:`WaterBridgeAnalysis.debug`.

        See Also
        --------
        :meth:`WaterBridgeAnalysis.generate_table` :
               processing the data into a different format.
        """
        self._setup_frames(self.u.trajectory, start, stop, step)

        logger.info("WBridge analysis: starting")
        logger.debug("WBridge analysis: donors    %r", self.donors)
        logger.debug("WBridge analysis: acceptors %r", self.acceptors)
        logger.debug("WBridge analysis: water bridge %r", self.water_selection)

        if debug is not None and debug != self.debug:
            self.debug = debug
            logger.debug("Toggling debug to %r", self.debug)
        if not self.debug:
            logger.debug("WBridge analysis: For full step-by-step debugging output use debug=True")

        self._timeseries = []
        self.timesteps = []
        self._water_network = []

        if verbose is None:
            verbose = self._verbose
        pm = ProgressMeter(self.n_frames,
                           format="WBridge frame {current_step:5d}: {step:5d}/{numsteps} [{percentage:5.1f}%]\r",
                           verbose=verbose)

        logger.info("Starting analysis (frame index start=%d stop=%d, step=%d)",
                    self.start, self.stop, self.step)

        for progress, ts in enumerate(self.u.trajectory[self.start:self.stop:self.step]):
            # all bonds for this timestep

            # dict of tuples (atom.index, atom.index) for quick check if
            # we already have the bond (to avoid duplicates)

            frame = ts.frame
            timestep = ts.time
            self.timesteps.append(timestep)
            pm.echo(progress, current_step=frame)
            self.logger_debug("Analyzing frame %(frame)d, timestep %(timestep)f ps", vars())
            if self.update_selection1:
                self._update_selection_1()
            if self.update_selection2:
                self._update_selection_2()
            if self.update_water_selection:
                self._update_water_selection()

            s1_frame_results_dict = defaultdict(list)
            if (self.selection1_type in ('donor', 'both') and
                self._water_acceptors):

                self.logger_debug("Selection 1 Donors <-> Water Acceptors")
                ns_acceptors = AtomNeighborSearch(self._water_acceptors)
                for i, donor_h_set in self._s1_donors_h.items():
                    d = self._s1_donors[i]
                    for h in donor_h_set:
                        res = ns_acceptors.search(h, self.distance)
                        for a in res:
                            donor_atom = h if self.distance_type != 'heavy' else d
                            dist = distances.calc_bonds(donor_atom.position,
                                                        a.position)
                            if dist <= self.distance:
                                angle = distances.calc_angles(d.position, h.position,
                                                             a.position)
                                angle = np.rad2deg(angle)
                                if angle >= self.angle:
                                    self.logger_debug(
                                        "S1-D: {0!s} <-> W-A: {1!s} {2:f} A, {3:f} DEG"\
                                        .format(h.index, a.index, dist, angle))
                                    s1_frame_results_dict[(a.resname, a.resid)].append(
                                        (h.index, a.index,
                                        (h.resname, h.resid, h.name),
                                        (a.resname, a.resid, a.name),
                                        dist, angle))

            if (self.selection1_type in ('acceptor', 'both') and
                self._s1_acceptors):

                self.logger_debug("Selection 1 Acceptors <-> Water Donors")
                ns_acceptors = AtomNeighborSearch(self._s1_acceptors)
                for i, donor_h_set in self._water_donors_h.items():
                    d = self._water_donors[i]
                    for h in donor_h_set:
                        res = ns_acceptors.search(h, self.distance)
                        for a in res:
                            donor_atom = h if self.distance_type != 'heavy' else d
                            dist = distances.calc_bonds(donor_atom.position,
                                                        a.position)
                            if dist <= self.distance:
                                angle = distances.calc_angles(d.position, h.position,
                                                             a.position)
                                angle = np.rad2deg(angle)
                                if angle >= self.angle:
                                    self.logger_debug(
                                        "S1-A: {0!s} <-> W-D: {1!s} {2:f} A, {3:f} DEG"\
                                        .format(a.index, h.index, dist, angle))
                                    s1_frame_results_dict[(h.resname, h.resid)].append(
                                        (h.index, a.index,
                                        (h.resname, h.resid, h.name),
                                        (a.resname, a.resid, a.name),
                                        dist, angle))

            # Narrow down the water selection
            selection_resn_id = list(s1_frame_results_dict.keys())
            if not selection_resn_id:
                self._timeseries.append([])
                continue
            selection_resn_id = ['(resname {} and resid {})'.format(
                resname, resid) for resname, resid in selection_resn_id]
            water_bridges = self._water.select_atoms(' or '.join(selection_resn_id))
            self.logger_debug("Size of water bridge selection: {0} atoms".format(len(water_bridges)))
            if not water_bridges:
                logger.warning("No water forming hydrogen bonding with selection 1.")
            water_bridges_donors = water_bridges.select_atoms(
                'name {0}'.format(' '.join(self.donors)))
            water_bridges_donors_h = {}
            for i, d in enumerate(water_bridges_donors):
                tmp = self._get_bonded_hydrogens(d)
                if tmp:
                    water_bridges_donors_h[i] = tmp
            self.logger_debug("water bridge donors: {0}".format(len(water_bridges_donors)))
            self.logger_debug("water bridge donor hydrogens: {0}".format(len(water_bridges_donors_h)))
            water_bridges_acceptors = water_bridges.select_atoms(
                'name {0}'.format(' '.join(self.acceptors)))
            self.logger_debug("water bridge: {0}".format(len(water_bridges_acceptors)))

            # Finding the hydrogen bonds between water bridge and selection 2
            s2_frame_results_dict = defaultdict(list)
            if self._s2_acceptors:
                self.logger_debug("Water bridge Donors <-> Selection 2 Acceptors")
                ns_acceptors = AtomNeighborSearch(self._s2_acceptors)
                for i, donor_h_set in water_bridges_donors_h.items():
                    d = water_bridges_donors[i]
                    for h in donor_h_set:
                        res = ns_acceptors.search(h, self.distance)
                        for a in res:
                            donor_atom = h if self.distance_type != 'heavy'  else d
                            dist = distances.calc_bonds(donor_atom.position,
                                                        a.position)
                            if dist <= self.distance:
                                angle = distances.calc_angles(d.position, h.position,
                                                             a.position)
                                angle = np.rad2deg(angle)
                                if angle >= self.angle:
                                    self.logger_debug(
                                        "WB-D: {0!s} <-> S2-A: {1!s} {2:f} A, {3:f} DEG"\
                                        .format(h.index, a.index, dist, angle))
                                    s2_frame_results_dict[(h.resname, h.resid)].append(
                                        (h.index, a.index,
                                        (h.resname, h.resid, h.name),
                                        (a.resname, a.resid, a.name),
                                        dist, angle))

            if water_bridges_acceptors:
                self.logger_debug("Selection 2 Donors <-> Selection 2 Acceptors")
                ns_acceptors = AtomNeighborSearch(water_bridges_acceptors)
                for i, donor_h_set in self._s2_donors_h.items():
                    d = self._s2_donors[i]
                    for h in donor_h_set:
                        res = ns_acceptors.search(h, self.distance)
                        for a in res:
                            donor_atom = h if self.distance_type != 'heavy' else d
                            dist = distances.calc_bonds(donor_atom.position,
                                                        a.position)
                            if dist <= self.distance:
                                angle = distances.calc_angles(d.position, h.position,
                                                             a.position)
                                angle = np.rad2deg(angle)
                                if angle >= self.angle:
                                    self.logger_debug(
                                        "WB-A: {0!s} <-> S2-D: {1!s} {2:f} A, {3:f} DEG"\
                                        .format(a.index, h.index, dist, angle))
                                    s2_frame_results_dict[(a.resname, a.resid)].append(
                                        (h.index, a.index,
                                        (h.resname, h.resid, h.name),
                                        (a.resname, a.resid, a.name),
                                        dist, angle))

            # Generate the water network
            water_network = {}
            for key in s2_frame_results_dict:
                s1_frame_results = set(s1_frame_results_dict[key])
                s2_frame_results = set(s2_frame_results_dict[key])
                if len(s1_frame_results.union(s2_frame_results)) > 1:
                    # Thus if selection 1 and selection 2 are the same and both
                    # only form a single hydrogen bond with a water, this entry
                    # won't be included.
                    water_network[key] = [s1_frame_results,
                    s2_frame_results.difference(s1_frame_results)]
            # Generate frame_results
            frame_results = []
            for s1_frame_results, s2_frame_results in water_network.values():
                frame_results.extend(list(s1_frame_results))
                frame_results.extend(list(s2_frame_results))

            self._timeseries.append(frame_results)
            self._water_network.append(water_network)


        logger.info("WBridge analysis: complete; timeseries  %s.timeseries",
                    self.__class__.__name__)
def pair_angles(structure,
                trajectory,
                start=0,
                stop=-1,
                step=1,
                cutoff=6.0,
                costheta=False):
    '''calclates the angles between the end to end vectors of oantigen neighbours over a given trajectory'''
    u = mda.Universe(structure, trajectory)

    if stop == -1:
        stop = u.trajectory.n_frames
    start, stop, step = u.trajectory.check_slice_indices(start, stop, step)
    num_steps = len(range(start, stop, step))
    if num_steps == 0:
        raise ValueError(
            "Selected time interval does not exist in the trajectory")

    oantigens = u.select_atoms("resname OANT").residues
    sugars_all = oantigens.atoms.select_atoms("name O*")
    sugars = sugars_all.split("residue")

    angles = []
    angles2 = []
    for frame in u.trajectory[start:stop:step]:
        vectors = {}
        head_endpoints = {}
        tail_cogs = {}
        for sugar in sugars:
            resid = sugar.resids[0]
            tail = sugar.select_atoms("name O51 to O54")
            head = sugar.select_atoms("name O97 to O99")
            head_cog = head.center_of_geometry()
            tail_cog = tail.center_of_geometry()
            vector = head_cog - tail_cog
            vector /= np.linalg.norm(vector)

            tail_cogs[resid] = tail_cog
            head_endpoints[resid] = tail_cog + vector
            vectors[resid] = vector
        tree = AtomNeighborSearch(sugars_all, box=u.dimensions)

        for sugar in sugars:
            near = tree.search(sugar, cutoff, level='R')
            for neighbour in near:
                resid1 = neighbour.resid
                resid2 = sugar.resids[0]
                if resid1 != resid2:
                    vec1 = vectors[resid1]
                    vec2 = vectors[resid2]

                    angle = get_tilt(vec1, vec2)

                    # determine if oantigen chains face each other
                    d1 = np.linalg.norm(tail_cogs[resid1] - tail_cogs[resid2])
                    d2 = np.linalg.norm(head_endpoints[resid1] -
                                        head_endpoints[resid2])
                    if d2 > d1:
                        angle2 = 0. - angle
                    else:
                        angle2 = angle

                    angles.append(angle)
                    angles2.append(angle2)
    return angles, angles2