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")
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")
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
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))
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))
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 _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
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
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])
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 _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
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")
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
def _single_frame(self): angle = calc_angles(self.ag1.positions, self.ag2.positions, self.ag3.positions, box=self.ag1.dimensions) self.result.append(angle)