Example #1
0
    def test_angles(self):
        from MDAnalysis.lib.distances import calc_angles
        # Shift atom coordinates a few box lengths in random directions and see if we still get same results
        a2 = (self.a + self.box * (-1, 0, 0)).astype(
            np.float32)  # seem to get converted to float64 otherwise
        b2 = (self.b + self.box * (1, 0, 1)).astype(np.float32)
        c2 = (self.c + self.box * (-2, 5, -7)).astype(np.float32)

        ref = calc_angles(self.a, self.b, self.c, backend=self.backend)

        test1 = calc_angles(a2,
                            self.b,
                            self.c,
                            box=self.box,
                            backend=self.backend)
        test2 = calc_angles(self.a,
                            b2,
                            self.c,
                            box=self.box,
                            backend=self.backend)
        test3 = calc_angles(self.a,
                            self.b,
                            c2,
                            box=self.box,
                            backend=self.backend)
        test4 = calc_angles(a2, b2, c2, box=self.box, backend=self.backend)

        for val in [test1, test2, test3, test4]:
            assert_almost_equal(
                ref,
                val,
                self.prec,
                err_msg="Min image in angle calculation failed")
Example #2
0
    def test_angles(self):
        from MDAnalysis.lib.distances import calc_angles
        # Shift atom coordinates a few box lengths in random directions and see if we still get same results
        a2 = (self.a + self.box * (-1, 0, 0)).astype(np.float32)  # seem to get converted to float64 otherwise
        b2 = (self.b + self.box * (1, 0, 1)).astype(np.float32)
        c2 = (self.c + self.box * (-2, 5, -7)).astype(np.float32)

        ref = calc_angles(self.a, self.b, self.c, backend=self.backend)

        test1 = calc_angles(a2, self.b, self.c, box=self.box, backend=self.backend)
        test2 = calc_angles(self.a, b2, self.c, box=self.box, backend=self.backend)
        test3 = calc_angles(self.a, self.b, c2, box=self.box, backend=self.backend)
        test4 = calc_angles(a2, b2, c2, box=self.box, backend=self.backend)

        for val in [test1, test2, test3, test4]:
            assert_almost_equal(ref, val, self.prec, err_msg="Min image in angle calculation failed")
Example #3
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
Example #4
0
 def test_right_type_angles(self):
     assert_equal(self.agroup.angles(),
                  calc_angles(self.agroup.atom1.positions,
                              self.agroup.atom2.positions,
                              self.agroup.atom3.positions))
     assert_equal(self.agroup.angles(pbc=True),
                  calc_angles(self.agroup.atom1.positions,
                              self.agroup.atom2.positions,
                              self.agroup.atom3.positions,
                              box=self.u.dimensions))
     assert_equal(self.agroup.values(),
                  calc_angles(self.agroup.atom1.positions,
                              self.agroup.atom2.positions,
                              self.agroup.atom3.positions))
     assert_equal(self.agroup.values(pbc=True),
                  calc_angles(self.agroup.atom1.positions,
                              self.agroup.atom2.positions,
                              self.agroup.atom3.positions,
                              box=self.u.dimensions))
 def test_right_type_angles(self, agroup, PSFDCD):
     assert_equal(agroup.angles(),
                  calc_angles(agroup.atom1.positions,
                              agroup.atom2.positions,
                              agroup.atom3.positions))
     assert_equal(agroup.angles(pbc=True),
                  calc_angles(agroup.atom1.positions,
                              agroup.atom2.positions,
                              agroup.atom3.positions,
                              box=PSFDCD.dimensions))
     assert_equal(agroup.values(),
                  calc_angles(agroup.atom1.positions,
                              agroup.atom2.positions,
                              agroup.atom3.positions))
     assert_equal(agroup.values(pbc=True),
                  calc_angles(agroup.atom1.positions,
                              agroup.atom2.positions,
                              agroup.atom3.positions,
                              box=PSFDCD.dimensions))
Example #6
0
 def test_right_type_angles(self, agroup, PSFDCD):
     assert_equal(
         agroup.angles(),
         calc_angles(agroup.atom1.positions, agroup.atom2.positions,
                     agroup.atom3.positions))
     assert_equal(
         agroup.angles(pbc=True),
         calc_angles(agroup.atom1.positions,
                     agroup.atom2.positions,
                     agroup.atom3.positions,
                     box=PSFDCD.dimensions))
     assert_equal(
         agroup.values(),
         calc_angles(agroup.atom1.positions, agroup.atom2.positions,
                     agroup.atom3.positions))
     assert_equal(
         agroup.values(pbc=True),
         calc_angles(agroup.atom1.positions,
                     agroup.atom2.positions,
                     agroup.atom3.positions,
                     box=PSFDCD.dimensions))
Example #7
0
 def test_right_type_angles(self):
     assert_equal(
         self.agroup.angles(),
         calc_angles(self.agroup.atom1.positions,
                     self.agroup.atom2.positions,
                     self.agroup.atom3.positions))
     assert_equal(
         self.agroup.angles(pbc=True),
         calc_angles(self.agroup.atom1.positions,
                     self.agroup.atom2.positions,
                     self.agroup.atom3.positions,
                     box=self.u.dimensions))
     assert_equal(
         self.agroup.values(),
         calc_angles(self.agroup.atom1.positions,
                     self.agroup.atom2.positions,
                     self.agroup.atom3.positions))
     assert_equal(
         self.agroup.values(pbc=True),
         calc_angles(self.agroup.atom1.positions,
                     self.agroup.atom2.positions,
                     self.agroup.atom3.positions,
                     box=self.u.dimensions))
Example #8
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)
def getInterAtomicAnglesForInpGeom(inpCell, angleIndices, degrees=True):
    """ Gets a list of requested angles between atoms for inpCell taking PBCs into account.
	
	Args:
		inpCell: (plato_pylib UnitCell object)
		angleIndices: (iter of len-3 iters) Each element contains [idxA,idxB,idxC] which means calculate the angle between idA,idxB,idxC for indices in inpCell.cartCoords
		degrees: (Bool) If True then return angles in degrees; else use radians

	Returns
		outAngles: (iter of floats) Length is the same as len(angleIndices); each is an angle calculated for a value in angleIndices
 
	"""
    #1) Check indices not empty; if empty just return empty list
    if len(angleIndices) == 0:
        return list()

    cartCoords = inpCell.cartCoords

    #Convert to format needed for mdAnalysis function
    numbAngles = len(angleIndices)
    cartCoordsA = np.array([
        np.array(cartCoords[angleIndices[idx][0]][:3])
        for idx in range(numbAngles)
    ])
    cartCoordsB = np.array([
        np.array(cartCoords[angleIndices[idx][1]][:3])
        for idx in range(numbAngles)
    ])
    cartCoordsC = np.array([
        np.array(cartCoords[angleIndices[idx][2]][:3])
        for idx in range(numbAngles)
    ])

    #Calculate using md analysis
    dims = mdAnalysisInter.getMDAnalysisDimsFromUCellObj(inpCell)
    outAnglesRadians = distLib.calc_angles(cartCoordsA,
                                           cartCoordsB,
                                           cartCoordsC,
                                           box=dims)
    outAnglesRadians = [x for x in outAnglesRadians]

    #Convert output to the form i want
    if degrees:
        outAngles = [math.degrees(x) for x in outAnglesRadians]
    else:
        outAngles = outAnglesRadians

    return outAngles
Example #10
0
def ang_measure(sel1, sel2, sel3):
    """
    This functions measures the angle between 3 specified atoms and returns the value between 0 and 360 degrees.
    The input selections have to be single atoms.
    """
    from numpy import rad2deg

    for sel in (sel1, sel2, sel3):
        if len(sel) != 1:
            raise NotSingleAtomSelectionError

    return ((float(
        rad2deg(
            mdadist.calc_angles(sel1.positions,
                                sel2.positions,
                                sel3.positions,
                                backend='OpenMP')))) + 360) % 360
Example #11
0
def aops(oxy, ts):
    #oxy = u.select_atoms('type 3')
    ts1 = center_in_box(oxy, wrap=True)(ts)
    oxy.atoms.wrap()
    dists = sp.spatial.distance.squareform(sda(oxy.positions,
                                           oxy.dimensions))
    # in format (x-pos, aop)
    AOPs = np.ones((len(oxy), 2))
    all_inds = []
    num_each = []
    for i in range(len(oxy)):
        nearby = np.where(dists[i] <= 3.5)[0]
        nearby = nearby[nearby != i]
        if nearby.size > 1:
            AOPs[i, 0] = oxy[i].position[0]
            inds = np.array(list(combinations(nearby, 2)))
            combs = inds.shape[0]
            xyz_inds = np.insert(inds, 1, np.full(combs, i), axis=1)
            all_inds.append(xyz_inds)
            num_each.append(combs)
        elif nearby.size == 1:
            num_each.append(0)
            AOPs[i, 0] = oxy[i].position[0]
            AOPs[i, 1] = 0.1 # it has one neighbor, so just say it's liquid
        else:
            num_each.append(0)
            AOPs[i, 0] = np.nan
    all_pos = oxy.positions[np.concatenate(all_inds)]
    angles = calc_angles(all_pos[:, 0, :], all_pos[:, 1, :],
                         all_pos[:, 2, :], box=oxy.dimensions)
    i = 0
    # go through the angles and calculate AOP
    for j, num in enumerate(num_each):
        AOPs[j, 1] = aop(angles[i:i+num])
        i += num
    # remove the ones that were too far away to begin with
    # AOPs = AOPs[~np.isnan(AOPs).any(axis=1)]
    # left, right = np.min(oxy.positions[:, 0]), np.max(oxy.positions[:, 0])
    # AOP_means = stats.binned_statistic(AOPs[:, 0], AOPs[:, 1], bins=8)
    return AOPs
def calcSingleAngleBetweenCoords_minImageConv(inpCell, coordA, coordB, coordC):
    """ Gets the angle (ABC) between three co-ordinates in inpCell using the minimum image convention; thus, this will use the closest possible A,B,C versions
	
	Args:
		inpCell: (plato_pylib UnitCell object) We use this to get the lattice vectors needed to account for PBCs
		coordA: (len 3 iter) Co-ordinates of first atom
		coordB: (len 3 iter) Co-ordinates of second atom
		coordC: (len 3 iter) Co-ordinates of third atom
 
	Returns
		angle: (float) The angle (in degrees) between the co-ordinates after taking PBCs into account
 
	"""
    dims = mdAnalysisInter.getMDAnalysisDimsFromUCellObj(inpCell)
    args = [
        np.array([coordA[:3]]),
        np.array([coordB[:3]]),
        np.array([coordC[:3]])
    ]
    angles = distLib.calc_angles(*args, box=dims)
    assert len(angles) == 1
    return math.degrees(angles[0])
Example #13
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__)
Example #14
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
        d = distance_array(self.h.positions, self.a.positions, box=box)
        if self.exclusions:
            # set to above dist crit to exclude
            d[self.exclusions] = self.d_crit + 1.0

        # find which partners satisfy distance criteria
        hidx, aidx = np.where(d < self.d_crit)

        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 is 'continuous':
                # Remove losers for continuous definition
                hidx = hidx[np.where(winners)]
                aidx = aidx[np.where(winners)]
            elif self.bond_type is '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
Example #15
0
def main():
    """Run main procedure."""
    # TODO(schneiderfelipe): accept multiple files
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("traj_files", nargs="+")
    args = parser.parse_args()

    gnorms = []
    energies = []
    all_atomnos = []
    all_atomcoords = []
    for traj_file in args.traj_files:
        atomnos, comments, atomcoords = read_xyz(traj_file)
        all_atomnos.extend(atomnos)
        all_atomcoords.extend(atomcoords)
        for comment in comments:
            fields = comment.split()
            gnorms.append(float(fields[3]))
            energies.append(float(fields[1]))
    energies = np.array(energies)
    energies -= energies.min()
    energies *= hartree * N_A / (kilo * calorie)

    u = mda.Universe.empty(n_atoms=len(all_atomnos[0]), trajectory=True)
    u.add_TopologyAttr("type", [element[i] for i in all_atomnos[0]])
    u.load_new(all_atomcoords, order="fac")
    print(u)

    selection = None
    print("(enter 'q' for exit, 'h' for help)")
    while True:
        code = input("select> ").strip().split()
        if code[0] == "q":
            break
        elif code[0] == "h":
            for key in commands:
                print(f"{key:15s}: {commands[key]}")
        elif code[0] == "e":
            fig, ax = plt.subplots(2)
            ax[0].plot(energies)
            ax[0].set_xlabel("frame")
            ax[0].set_ylabel("energy (kcal/mol)")

            ax[1].plot(gnorms)
            ax[1].set_xlabel("frame")
            ax[1].set_ylabel("grad. norm (Eh/a0)")
            plt.show()
        elif code[0] == "s":
            print(selection)
            if selection is not None:
                print(selection_text)
        elif code[0] == "pca":
            if selection is None:
                print("empty selection, doing nothing")
                continue

            p = pca.PCA(u, select=selection_text)
            p.run()

            n_pcs = np.where(p.cumulated_variance > 0.95)[0][0]
            print(n_pcs)
            print(p.cumulated_variance[0:n_pcs])
            pca_space = p.transform(selection, n_components=n_pcs)
            print(pca_space)
            print(pca.cosine_content(pca_space, 0))
        elif code[0] == "p":
            if selection is None:
                print("empty selection, doing nothing")
                continue

            n = len(selection)
            if n == 2:
                data_label = "bond length (Å)"
            elif n == 3:
                data_label = "bond angle (°)"
            elif n == 4:
                data_label = "dihedral angle (°)"
            else:
                print("too few or too many indices")
                continue

            data = []
            for i, (e, ts) in enumerate(zip(energies, u.trajectory)):
                if n == 2:
                    d = distances.calc_bonds(
                        selection[0].position, selection[1].position
                    )
                elif n == 3:
                    d = np.degrees(
                        distances.calc_angles(
                            selection[0].position,
                            selection[1].position,
                            selection[2].position,
                        )
                    )
                elif n == 4:
                    d = np.degrees(
                        distances.calc_dihedrals(
                            selection[0].position,
                            selection[1].position,
                            selection[2].position,
                            selection[3].position,
                        )
                    )

                data.append(d)
                if i % 100 == 0 or i == len(u.trajectory) - 1:
                    print(
                        f"frame = {ts.frame:4d}: e = {e:5.1f} kcal/mol, {data_label.split('(')[0][:-1]} = {d:7.3f} {data_label[-2]}"
                    )
            data = np.array(data)

            fig, ax = plt.subplots(1, 2)
            ax[0].plot(data)
            ax[0].set_xlabel("frame")
            ax[0].set_ylabel(data_label)

            ax[1].plot(energies, data, "o", label="data points")
            ax[1].set_xlabel("energy (kcal/mol)")
            ax[1].set_ylabel(data_label)

            if n == 2:
                dx = 0.1
            elif n == 3:
                dx = 10.0
            elif n == 4:
                dx = 10.0
            res = stats.binned_statistic(
                data, energies, "min", min(25, (data.max() - data.min()) / dx)
            )

            # print(res.statistic)
            mask = np.isnan(res.statistic)
            res.statistic[mask] = np.interp(
                np.flatnonzero(mask), np.flatnonzero(~mask), res.statistic[~mask]
            )
            # print(res.statistic)

            # ax[1].hlines(res.statistic, res.bin_edges[:-1], res.bin_edges[1:], colors='g', lw=2, label='binned min. energies')
            ax[1].barh(
                (res.bin_edges[:-1] + res.bin_edges[1:]) / 2,
                res.statistic,
                align="center",
                height=res.bin_edges[1:] - res.bin_edges[:-1],
                alpha=0.25,
                label="binned min. energies",
            )
            ax[1].legend()

            plt.show()

        else:
            try:
                selection_text = " ".join(code)
                selection = u.select_atoms(selection_text)
            except mda.exceptions.SelectionError as e:
                print(e)

    print("bye")
Example #16
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
        d = distance_array(self.h.positions, self.a.positions, box=box)
        if self.exclusions:
            # set to above dist crit to exclude
            d[self.exclusions] = self.d_crit + 1.0

        # find which partners satisfy distance criteria
        hidx, aidx = numpy.where(d < self.d_crit)

        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 = numpy.where(a > self.a_crit)
        hidx = hidx[idx2]
        aidx = aidx[idx2]

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

        if self.time_cut:
            # counter for time criteria
            count = numpy.zeros(nbonds, dtype=numpy.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 is 'continuous':
                # Remove losers for continuous definition
                hidx = hidx[numpy.where(winners)]
                aidx = aidx[numpy.where(winners)]
            elif self.bond_type is '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
Example #17
0
 def _single_frame(self):
     angle = calc_angles(self.ag1.positions,
                         self.ag2.positions,
                         self.ag3.positions,
                         box=self.ag1.dimensions)
     self.result.append(angle)