def rotation_angle(helix_vector, axis_vector, rotation_vector): reference_vector = np.cross(np.cross(helix_vector, axis_vector), helix_vector) second_reference_vector = np.cross(axis_vector, helix_vector) screw_angle = mdamath.angle(reference_vector, rotation_vector) alt_screw_angle = mdamath.angle(second_reference_vector, rotation_vector) updown = np.cross(reference_vector, rotation_vector) if not (np.pi < screw_angle < 3 * np.pi / 4): if screw_angle < np.pi / 4 and alt_screw_angle < np.pi / 2: screw_angle = np.pi / 2 - alt_screw_angle elif screw_angle < np.pi / 4 and alt_screw_angle > np.pi / 2: screw_angle = alt_screw_angle - np.pi / 2 elif screw_angle > 3 * np.pi / 4 and alt_screw_angle < np.pi / 2: screw_angle = np.pi / 2 + alt_screw_angle elif screw_angle > 3 * np.pi / 4 and alt_screw_angle > np.pi / 2: screw_angle = 3 * np.pi / 2 - alt_screw_angle else: logger.debug("Big Screw Up: screw_angle=%g degrees", np.rad2deg(screw_angle)) if mdamath.norm(updown) == 0: logger.warning("PROBLEM (vector is at 0 or 180)") helix_dot_rehelix = mdamath.angle(updown, helix_vector) #if ( helix_dot_rehelix < np.pi/2 and helix_dot_rehelix >= 0 )or helix_dot_rehelix <-np.pi/2: if (-np.pi / 2 < helix_dot_rehelix < np.pi / 2) or (helix_dot_rehelix > 3 * np.pi / 2): screw_angle = -screw_angle return screw_angle
def rotation_angle(helix_vector, axis_vector, rotation_vector): reference_vector = np.cross(np.cross(helix_vector, axis_vector), helix_vector) second_reference_vector = np.cross(axis_vector, helix_vector) screw_angle = mdamath.angle(reference_vector, rotation_vector) alt_screw_angle = mdamath.angle(second_reference_vector, rotation_vector) updown = np.cross(reference_vector, rotation_vector) if not (np.pi < screw_angle < 3 * np.pi / 4): if screw_angle < np.pi / 4 and alt_screw_angle < np.pi / 2: screw_angle = np.pi / 2 - alt_screw_angle elif screw_angle < np.pi / 4 and alt_screw_angle > np.pi / 2: screw_angle = alt_screw_angle - np.pi / 2 elif screw_angle > 3 * np.pi / 4 and alt_screw_angle < np.pi / 2: screw_angle = np.pi / 2 + alt_screw_angle elif screw_angle > 3 * np.pi / 4 and alt_screw_angle > np.pi / 2: screw_angle = 3 * np.pi / 2 - alt_screw_angle else: logger.debug("Big Screw Up: screw_angle=%g degrees", np.rad2deg(screw_angle)) if mdamath.norm(updown) == 0: logger.warn("PROBLEM (vector is at 0 or 180)") helix_dot_rehelix = mdamath.angle(updown, helix_vector) #if ( helix_dot_rehelix < np.pi/2 and helix_dot_rehelix >= 0 )or helix_dot_rehelix <-np.pi/2: if (-np.pi / 2 < helix_dot_rehelix < np.pi / 2) or (helix_dot_rehelix > 3 * np.pi / 2): screw_angle = -screw_angle return screw_angle
def vector_of_best_fit(origins): origins = np.asarray(origins) centroids = center(origins) M = origins - centroids A = np.dot(M.transpose(), M) u, s, vh = np.linalg.linalg.svd(A) vector = vh[0] #Correct vector to face towards first residues rough_helix = origins[0] - centroids agreement = mdamath.angle(rough_helix, vector) if not (-np.pi / 2 < agreement < np.pi / 2): vector *= -1 best_fit_tilt = mdamath.angle(vector, [0, 0, 1]) return vector, best_fit_tilt
def test_numpy_compliance(self): # Checks that the cython functions give identical results to the numpy versions bonds = MDAnalysis.lib.distances.calc_bonds(self.a, self.b, backend=self.backend) angles = MDAnalysis.lib.distances.calc_angles(self.a, self.b, self.c, backend=self.backend) dihedrals = MDAnalysis.lib.distances.calc_dihedrals(self.a, self.b, self.c, self.d, backend=self.backend) bonds_numpy = np.array([mdamath.norm(y - x) for x, y in zip(self.a, self.b)]) vec1 = self.a - self.b vec2 = self.c - self.b angles_numpy = np.array([mdamath.angle(x, y) for x, y in zip(vec1, vec2)]) ab = self.b - self.a bc = self.c - self.b cd = self.d - self.c dihedrals_numpy = np.array([mdamath.dihedral(x, y, z) for x, y, z in zip(ab, bc, cd)]) assert_almost_equal(bonds, bonds_numpy, self.prec, err_msg="Cython bonds didn't match numpy calculations") # numpy 0 angle returns NaN rather than 0 assert_almost_equal(angles[1:], angles_numpy[1:], self.prec, err_msg="Cython angles didn't match numpy calcuations") # same issue with first two dihedrals assert_almost_equal(dihedrals[2:], dihedrals_numpy[2:], self.prec, err_msg="Cython dihedrals didn't match numpy calculations")
def test_numpy_compliance(self, positions, backend): a, b, c, d = positions # Checks that the cython functions give identical results to the numpy versions bonds = MDAnalysis.lib.distances.calc_bonds(a, b, backend=backend) angles = MDAnalysis.lib.distances.calc_angles(a, b, c, backend=backend) dihedrals = MDAnalysis.lib.distances.calc_dihedrals(a, b, c, d, backend=backend) bonds_numpy = np.array([mdamath.norm(y - x) for x, y in zip(a, b)]) vec1 = a - b vec2 = c - b angles_numpy = np.array( [mdamath.angle(x, y) for x, y in zip(vec1, vec2)]) ab = a - b bc = b - c cd = c - d dihedrals_numpy = np.array( [mdamath.dihedral(x, y, z) for x, y, z in zip(ab, bc, cd)]) assert_almost_equal( bonds, bonds_numpy, self.prec, err_msg="Cython bonds didn't match numpy calculations") # numpy 0 angle returns NaN rather than 0 assert_almost_equal( angles[1:], angles_numpy[1:], self.prec, err_msg="Cython angles didn't match numpy calcuations") assert_almost_equal( dihedrals, dihedrals_numpy, self.prec, err_msg="Cython dihedrals didn't match numpy calculations")
def __angle__(self, reference, target): v1 = [reference[0], reference[1], 0] v2 = [target[0], target[1], 0] angle = mdmath.angle(v1, v2) return np.degrees(angle)
def helanal_trajectory(universe, selection="name CA", start=None, end=None, begin=None, finish=None, matrix_filename="bending_matrix.dat", origin_pdbfile="origin.pdb", summary_filename="summary.txt", screw_filename="screw.xvg", tilt_filename="local_tilt.xvg", fitted_tilt_filename="fit_tilt.xvg", bend_filename="local_bend.xvg", twist_filename="unit_twist.xvg", prefix="helanal_", ref_axis=None, quiet=False): """Perform HELANAL_ helix analysis on all frames in *universe*. .. Note:: Only a single helix is analyzed. Use the selection to specify the helix, e.g. with "name CA and resid 1:20" or use start=1, stop=20. :Arguments: *universe* :class:`~MDAnalysis.core.AtomGroup.Universe` :Keywords: *selection* selection string that selects Calpha atoms [``"name CA"``] *start* start residue resid *end* end residue resid *begin* start analysing for time (ps) >= *begin*; ``None`` starts from the beginning [``None``] *finish* stop analysis for time (ps) =< *finish*; ``None`` goes to the end of the trajectory [``None``] *matrix_filename* Output file- bending matrix [``"bending_matrix.dat"``] *origin_pdbfile* Output file- origin pdb file [``"origin.pdb"``] *summary_filename* Output file- all of the basic data [``"summary.txt"``] *screw_filename* Output file- local tilts of individual residues from 2 to n-1 [``"screw.xvg"``] *tilt_filename* Output file- tilt of line of best fit applied to origin axes [``"local_tilt.xvg"``] *bend_filename* Output file- local bend angles between successive local helix axes [``"local_bend.xvg"``] *twist_filename* Output file- local unit twist between successive helix turns [``"unit_twist.xvg"``] *prefix* Prefix to add to all output file names; set to ``None`` to disable [``"helanal__"``] *ref_axis* Calculate tilt angle relative to the axis; if ``None`` then ``[0,0,1]`` is chosen [``None``] *quiet* Suppress most diagnostic output. :Raises: FinishTimeException If the specified finish time precedes the specified start time or current time stamp of trajectory object. .. versionchanged:: 0.13.0 New *quiet* keyword to silence frame progress output and most of the output that used to be printed to stdout is now logged to the logger *MDAnalysis.analysis.helanal* (at logelevel *INFO*). """ if ref_axis is None: ref_axis = np.array([0., 0., 1.]) else: # enable MDA API so that one can use a tuple of atoms or AtomGroup with # two atoms ref_axis = np.asarray(ref_axis) if not (start is None and end is None): if start is None: start = universe.atoms[0].resid if end is None: end = universe.atoms[-1].resid selection += " and resid {start:d}:{end:d}".format(**vars()) ca = universe.select_atoms(selection) trajectory = universe.trajectory if finish is not None: if trajectory.ts.time > finish: # you'd be starting with a finish time (in ps) that has already passed or not # available raise FinishTimeException( 'The input finish time ({finish} ps) precedes the current trajectory time of {traj_time} ps.' .format(finish=finish, traj_time=trajectory.time)) if start is not None and end is not None: logger.info("Analysing from residue %d to %d", start, end) elif start is not None and end is None: logger.info("Analysing from residue %d to the C termini", start) elif start is None and end is not None: logger.info("Analysing from the N termini to %d", end) logger.info("Analysing %d/%d residues", ca.n_atoms, universe.atoms.n_residues) if prefix is not None: prefix = str(prefix) matrix_filename = prefix + matrix_filename origin_pdbfile = prefix + origin_pdbfile summary_filename = prefix + summary_filename screw_filename = prefix + screw_filename tilt_filename = prefix + tilt_filename fitted_tilt_filename = prefix + fitted_tilt_filename bend_filename = prefix + bend_filename twist_filename = prefix + twist_filename backup_file(matrix_filename) backup_file(origin_pdbfile) backup_file(summary_filename) backup_file(screw_filename) backup_file(tilt_filename) backup_file(fitted_tilt_filename) backup_file(bend_filename) backup_file(twist_filename) global_height = [] global_twist = [] global_rnou = [] global_bending = [] global_bending_matrix = [] global_tilt = [] global_fitted_tilts = [] global_screw = [] pm = ProgressMeter(trajectory.n_frames, quiet=quiet, format="Frame %(step)10d: %(time)20.1f ps\r") for ts in trajectory: pm.echo(ts.frame, time=ts.time) frame = ts.frame if begin is not None: if trajectory.time < begin: continue if finish is not None: if trajectory.time > finish: break ca_positions = ca.positions twist, bending_angles, height, rnou, origins, local_helix_axes, local_screw_angles = \ main_loop(ca_positions, ref_axis=ref_axis) origin_pdb(origins, origin_pdbfile) #calculate local bending matrix( it is looking at all i, j combinations) if len(global_bending_matrix) == 0: global_bending_matrix = [[[] for item in local_helix_axes] for item in local_helix_axes] for i in range(len(local_helix_axes)): for j in range(i + 1, len(local_helix_axes)): angle = np.rad2deg( np.arccos(np.dot(local_helix_axes[i], local_helix_axes[j]))) global_bending_matrix[i][j].append(angle) #global_bending_matrix[j][i].append(angle) #global_bending_matrix[i][i].append(0.) fit_vector, fit_tilt = vector_of_best_fit(origins) global_height += height global_twist += twist global_rnou += rnou #global_screw.append(local_screw_angles) global_fitted_tilts.append(np.rad2deg(fit_tilt)) #print out rotations across the helix to a file with open(twist_filename, "a") as twist_output: print(frame, end='', file=twist_output) for loc_twist in twist: print(loc_twist, end='', file=twist_output) print("", file=twist_output) with open(bend_filename, "a") as bend_output: print(frame, end='', file=bend_output) for loc_bend in bending_angles: print(loc_bend, end='', file=bend_output) print("", file=bend_output) with open(screw_filename, "a") as rot_output: print(frame, end='', file=rot_output) for rotation in local_screw_angles: print(rotation, end='', file=rot_output) print("", file=rot_output) with open(tilt_filename, "a") as tilt_output: print(frame, end='', file=tilt_output) for tilt in local_helix_axes: print(np.rad2deg(mdamath.angle(tilt, ref_axis)), end='', file=tilt_output) print("", file=tilt_output) with open(fitted_tilt_filename, "a") as tilt_output: print(frame, np.rad2deg(fit_tilt), file=tilt_output) if len(global_bending) == 0: global_bending = [[] for item in bending_angles] #global_tilt = [ [] for item in local_helix_axes ] for store, tmp in zip(global_bending, bending_angles): store.append(tmp) #for store,tmp in zip(global_tilt,local_helix_axes): store.append(mdamath.angle(tmp,ref_axis)) twist_mean, twist_sd, twist_abdev = stats(global_twist) height_mean, height_sd, height_abdev = stats(global_height) rnou_mean, rnou_sd, rnou_abdev = stats(global_rnou) ftilt_mean, ftilt_sd, ftilt_abdev = stats(global_fitted_tilts) bending_statistics = [stats(item) for item in global_bending] #tilt_statistics = [ stats(item) for item in global_tilt] bending_statistics_matrix = [[stats(col) for col in row] for row in global_bending_matrix] with open(matrix_filename, 'w') as mat_output: print("Mean", file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[0]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) print('\nSD', file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[1]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) print("\nABDEV", file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[2]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) logger.info("Height: %g SD: %g ABDEV: %g (Angstroem)", height_mean, height_sd, height_abdev) logger.info("Twist: %g SD: %g ABDEV: %g", twist_mean, twist_sd, twist_abdev) logger.info("Residues/turn: %g SD: %g ABDEV: %g", rnou_mean, rnou_sd, rnou_abdev) logger.info("Fitted tilt: %g SD: %g ABDEV: %g", ftilt_mean, ftilt_sd, ftilt_abdev) logger.info("Local bending angles:") residue_statistics = zip(*bending_statistics) measure_names = ["Mean ", "SD ", "ABDEV"] if start is None: output = " ".join([ "{0:8d}".format(item) for item in range(4, len(residue_statistics[0]) + 4) ]) else: output = " ".join([ "{0:8d}".format(item) for item in range(start + 3, len(residue_statistics[0]) + start + 3) ]) logger.info("ResID %s", output) for measure, name in zip(residue_statistics, measure_names): output = str(name) + " " output += " ".join(["{0:8.1f}".format(residue) for residue in measure]) logger.info(output) with open(summary_filename, 'w') as summary_output: print("Height:", height_mean, "SD", height_sd, "ABDEV", height_abdev, '(nm)', file=summary_output) print("Twist:", twist_mean, "SD", twist_sd, "ABDEV", twist_abdev, file=summary_output) print("Residues/turn:", rnou_mean, "SD", rnou_sd, "ABDEV", rnou_abdev, file=summary_output) print("Local bending angles:", file=summary_output) residue_statistics = list(zip(*bending_statistics)) measure_names = ["Mean ", "SD ", "ABDEV"] print("ResID", end='', file=summary_output) if start is None: for item in range(4, len(residue_statistics[0]) + 4): output = "{0:8d}".format(item) print(output, end='', file=summary_output) else: for item in range(start + 3, len(residue_statistics[0]) + start + 3): output = "{0:8d}".format(item) print(output, end='', file=summary_output) print('', file=summary_output) for measure, name in zip(residue_statistics, measure_names): print(name, end='', file=summary_output) for residue in measure: output = "{0:8.1f}".format(residue) print(output, end='', file=summary_output) print('', file=summary_output)
def testAngleVectors(self): assert_equal(mdamath.angle(2 * self.e1, self.e2), pi / 2) assert_equal(mdamath.angle(-2 * self.e1, self.e2), pi - pi / 2) assert_equal(mdamath.angle(23.3 * self.e1, self.a), pi / 3)
def testAngleRandom(self): for x in np.random.uniform(0, np.pi, 20): r = np.random.uniform(0, 1000) v = r * np.array([np.cos(x), np.sin(x), 0]) assert_almost_equal(mdamath.angle(self.e1, v), x, 6)
def test_angle_pi(self, x_axis, y_axis, value): assert_almost_equal(mdamath.angle(x_axis, y_axis), value)
def testAngleVectors(self): assert_equal(mdamath.angle(2 * self.e1, self.e2), np.pi / 2) assert_equal(mdamath.angle(-2 * self.e1, self.e2), np.pi - np.pi / 2) assert_equal(mdamath.angle(23.3 * self.e1, self.a), np.pi / 3)
def testAngleUnitvectors(self): assert_equal(mdamath.angle(self.e1, self.e2), np.pi / 2) assert_equal(mdamath.angle(self.e1, self.a), np.pi / 3)
fout = open(folder + 'cationpi.dat', 'w') for ts in u.trajectory: sys.stdout.write('\rTime = %d' % u.trajectory.time) boxvec = mdamath.triclinic_vectors(u.dimensions) for ipi in range(npigroup): pigroup = pigroups[ipi] picenter = pigroup.centroid(pbc=True) for icat in range(ncat): cation = cations[icat] dist = distances.calc_bonds(coords1=cation.position, coords2=picenter, box=u.dimensions) if dist < 7.0: vec = vector(cation.position, picenter, boxvec) v1 = vector(pigroup.positions[0], pigroup.positions[5], boxvec) v2 = vector(pigroup.positions[1], pigroup.positions[4], boxvec) v3 = vector(pigroup.positions[2], pigroup.positions[3], boxvec) n1 = mdamath.normal(v1, v2) n2 = mdamath.normal(v3, v1) n3 = mdamath.normal(v3, v2) n = (n1 + n2 + n3) angle = np.degrees(mdamath.angle(n, vec)) if angle > 120 or angle < 60: fout.write( '%.1f %d %s %d %s %.6f %.6f\n' % (u.trajectory.time, catresid[icat], catresname[icat], piresid[ipi], piresname[ipi], angle, dist)) sys.stdout.write('\n') fout.close()
def testAngleRandom(self): for x in numpy.random.uniform(0, pi, 20): r = numpy.random.uniform(0, 1000) v = r * numpy.array([cos(x), sin(x), 0]) assert_almost_equal(mdamath.angle(self.e1, v), x, 6)
def testAnglePi(self): assert_almost_equal(mdamath.angle(-2.3456e7 * self.e1, 3.4567e-6 * self.e1), pi) assert_almost_equal(mdamath.angle(2.3456e7 * self.e1, 3.4567e-6 * self.e1), 0.0)
def testAngleColinear(self): assert_equal(mdamath.angle(self.a, self.a), 0.0)
def testAngleNullVector(self): assert_equal(mdamath.angle(self.e1, self.null), numpy.nan)
def test_vectors(self, x_axis, y_axis, value): assert_equal(mdamath.angle(x_axis, y_axis), value)
def testAngleNullVector(self): assert_equal(mdamath.angle(self.e1, self.null), np.nan)
def test_angle_range(self, x): r = 1000. v = r * np.array([np.cos(x), np.sin(x), 0]) assert_almost_equal(mdamath.angle(self.e1, v), x, 6)
def helanal_trajectory(universe, selection="name CA", start=None, end=None, begin=None, finish=None, matrix_filename="bending_matrix.dat", origin_pdbfile="origin.pdb", summary_filename="summary.txt", screw_filename="screw.xvg", tilt_filename="local_tilt.xvg", fitted_tilt_filename="fit_tilt.xvg", bend_filename="local_bend.xvg", twist_filename="unit_twist.xvg", prefix="helanal_", ref_axis=None, quiet=False): """Perform HELANAL_ helix analysis on all frames in *universe*. .. Note:: Only a single helix is analyzed. Use the selection to specify the helix, e.g. with "name CA and resid 1:20" or use start=1, stop=20. :Arguments: *universe* :class:`~MDAnalysis.core.AtomGroup.Universe` :Keywords: *selection* selection string that selects Calpha atoms [``"name CA"``] *start* start residue resid *end* end residue resid *begin* start analysing for time (ps) >= *begin*; ``None`` starts from the beginning [``None``] *finish* stop analysis for time (ps) =< *finish*; ``None`` goes to the end of the trajectory [``None``] *matrix_filename* Output file- bending matrix [``"bending_matrix.dat"``] *origin_pdbfile* Output file- origin pdb file [``"origin.pdb"``] *summary_filename* Output file- all of the basic data [``"summary.txt"``] *screw_filename* Output file- local tilts of individual residues from 2 to n-1 [``"screw.xvg"``] *tilt_filename* Output file- tilt of line of best fit applied to origin axes [``"local_tilt.xvg"``] *bend_filename* Output file- local bend angles between successive local helix axes [``"local_bend.xvg"``] *twist_filename* Output file- local unit twist between successive helix turns [``"unit_twist.xvg"``] *prefix* Prefix to add to all output file names; set to ``None`` to disable [``"helanal__"``] *ref_axis* Calculate tilt angle relative to the axis; if ``None`` then ``[0,0,1]`` is chosen [``None``] *quiet* Suppress most diagnostic output. :Raises: FinishTimeException If the specified finish time precedes the specified start time or current time stamp of trajectory object. .. versionchanged:: 0.13.0 New *quiet* keyword to silence frame progress output and most of the output that used to be printed to stdout is now logged to the logger *MDAnalysis.analysis.helanal* (at logelevel *INFO*). """ if ref_axis is None: ref_axis = np.array([0., 0., 1.]) else: # enable MDA API so that one can use a tuple of atoms or AtomGroup with # two atoms ref_axis = np.asarray(ref_axis) if not (start is None and end is None): if start is None: start = universe.atoms[0].resid if end is None: end = universe.atoms[-1].resid selection += " and resid {start:d}:{end:d}".format(**vars()) ca = universe.select_atoms(selection) trajectory = universe.trajectory if finish is not None: if trajectory.ts.time > finish: # you'd be starting with a finish time (in ps) that has already passed or not # available raise FinishTimeException( 'The input finish time ({finish} ps) precedes the current trajectory time of {traj_time} ps.'.format( finish=finish, traj_time=trajectory.time)) if start is not None and end is not None: logger.info("Analysing from residue %d to %d", start, end) elif start is not None and end is None: logger.info("Analysing from residue %d to the C termini", start) elif start is None and end is not None: logger.info("Analysing from the N termini to %d", end) logger.info("Analysing %d/%d residues", ca.n_atoms, universe.atoms.n_residues) if prefix is not None: prefix = str(prefix) matrix_filename = prefix + matrix_filename origin_pdbfile = prefix + origin_pdbfile summary_filename = prefix + summary_filename screw_filename = prefix + screw_filename tilt_filename = prefix + tilt_filename fitted_tilt_filename = prefix + fitted_tilt_filename bend_filename = prefix + bend_filename twist_filename = prefix + twist_filename backup_file(matrix_filename) backup_file(origin_pdbfile) backup_file(summary_filename) backup_file(screw_filename) backup_file(tilt_filename) backup_file(fitted_tilt_filename) backup_file(bend_filename) backup_file(twist_filename) global_height = [] global_twist = [] global_rnou = [] global_bending = [] global_bending_matrix = [] global_tilt = [] global_fitted_tilts = [] global_screw = [] pm = ProgressMeter(trajectory.n_frames, quiet=quiet, format="Frame %(step)10d: %(time)20.1f ps\r") for ts in trajectory: pm.echo(ts.frame, time=ts.time) frame = ts.frame if begin is not None: if trajectory.time < begin: continue if finish is not None: if trajectory.time > finish: break ca_positions = ca.positions twist, bending_angles, height, rnou, origins, local_helix_axes, local_screw_angles = \ main_loop(ca_positions, ref_axis=ref_axis) origin_pdb(origins, origin_pdbfile) #calculate local bending matrix( it is looking at all i, j combinations) if len(global_bending_matrix) == 0: global_bending_matrix = [[[] for item in local_helix_axes] for item in local_helix_axes] for i in range(len(local_helix_axes)): for j in range(i + 1, len(local_helix_axes)): angle = np.rad2deg(np.arccos(np.dot(local_helix_axes[i], local_helix_axes[j]))) global_bending_matrix[i][j].append(angle) #global_bending_matrix[j][i].append(angle) #global_bending_matrix[i][i].append(0.) fit_vector, fit_tilt = vector_of_best_fit(origins) global_height += height global_twist += twist global_rnou += rnou #global_screw.append(local_screw_angles) global_fitted_tilts.append(np.rad2deg(fit_tilt)) #print out rotations across the helix to a file with open(twist_filename, "a") as twist_output: print(frame, end='', file=twist_output) for loc_twist in twist: print(loc_twist, end='', file=twist_output) print("", file=twist_output) with open(bend_filename, "a") as bend_output: print(frame, end='', file=bend_output) for loc_bend in bending_angles: print(loc_bend, end='', file=bend_output) print("", file=bend_output) with open(screw_filename, "a") as rot_output: print(frame, end='', file=rot_output) for rotation in local_screw_angles: print(rotation, end='', file=rot_output) print("", file=rot_output) with open(tilt_filename, "a") as tilt_output: print(frame, end='', file=tilt_output) for tilt in local_helix_axes: print(np.rad2deg(mdamath.angle(tilt, ref_axis)), end='', file=tilt_output) print("", file=tilt_output) with open(fitted_tilt_filename, "a") as tilt_output: print(frame, np.rad2deg(fit_tilt), file=tilt_output) if len(global_bending) == 0: global_bending = [[] for item in bending_angles] #global_tilt = [ [] for item in local_helix_axes ] for store, tmp in zip(global_bending, bending_angles): store.append(tmp) #for store,tmp in zip(global_tilt,local_helix_axes): store.append(mdamath.angle(tmp,ref_axis)) twist_mean, twist_sd, twist_abdev = stats(global_twist) height_mean, height_sd, height_abdev = stats(global_height) rnou_mean, rnou_sd, rnou_abdev = stats(global_rnou) ftilt_mean, ftilt_sd, ftilt_abdev = stats(global_fitted_tilts) bending_statistics = [stats(item) for item in global_bending] #tilt_statistics = [ stats(item) for item in global_tilt] bending_statistics_matrix = [[stats(col) for col in row] for row in global_bending_matrix] with open(matrix_filename, 'w') as mat_output: print("Mean", file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[0]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) print('\nSD', file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[1]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) print("\nABDEV", file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[2]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) logger.info("Height: %g SD: %g ABDEV: %g (Angstroem)", height_mean, height_sd, height_abdev) logger.info("Twist: %g SD: %g ABDEV: %g", twist_mean, twist_sd, twist_abdev) logger.info("Residues/turn: %g SD: %g ABDEV: %g", rnou_mean, rnou_sd, rnou_abdev) logger.info("Fitted tilt: %g SD: %g ABDEV: %g", ftilt_mean, ftilt_sd, ftilt_abdev) logger.info("Local bending angles:") residue_statistics = zip(*bending_statistics) measure_names = ["Mean ", "SD ", "ABDEV"] if start is None: output = " ".join(["{0:8d}".format(item) for item in range(4, len(residue_statistics[0]) + 4)]) else: output = " ".join(["{0:8d}".format(item) for item in range(start + 3, len(residue_statistics[0]) + start + 3)]) logger.info("ResID %s", output) for measure, name in zip(residue_statistics, measure_names): output = str(name) + " " output += " ".join(["{0:8.1f}".format(residue) for residue in measure]) logger.info(output) with open(summary_filename, 'w') as summary_output: print("Height:", height_mean, "SD", height_sd, "ABDEV", height_abdev, '(nm)', file=summary_output) print("Twist:", twist_mean, "SD", twist_sd, "ABDEV", twist_abdev, file=summary_output) print("Residues/turn:", rnou_mean, "SD", rnou_sd, "ABDEV", rnou_abdev, file=summary_output) print("Local bending angles:", file=summary_output) residue_statistics = list(zip(*bending_statistics)) measure_names = ["Mean ", "SD ", "ABDEV"] print("ResID", end='', file=summary_output) if start is None: for item in range(4, len(residue_statistics[0]) + 4): output = "{0:8d}".format(item) print(output, end='', file=summary_output) else: for item in range(start + 3, len(residue_statistics[0]) + start + 3): output = "{0:8d}".format(item) print(output, end='', file=summary_output) print('', file=summary_output) for measure, name in zip(residue_statistics, measure_names): print(name, end='', file=summary_output) for residue in measure: output = "{0:8.1f}".format(residue) print(output, end='', file=summary_output) print('', file=summary_output)
def helanal_trajectory(universe, select="name CA", begin=None, finish=None, matrix_filename="bending_matrix.dat", origin_pdbfile="origin.pdb", summary_filename="summary.txt", screw_filename="screw.xvg", tilt_filename="local_tilt.xvg", fitted_tilt_filename="fit_tilt.xvg", bend_filename="local_bend.xvg", twist_filename="unit_twist.xvg", prefix="helanal_", ref_axis=None, verbose=False): """Perform HELANAL helix analysis on all frames in `universe`. Parameters ---------- universe : Universe select : str (optional) selection string that selects Calpha atoms [``"name CA"``] begin : float (optional) start analysing for time (ps) >= *begin*; ``None`` starts from the beginning [``None``] finish : float (optional) stop analysis for time (ps) =< *finish*; ``None`` goes to the end of the trajectory [``None``] matrix_filename : str (optional) Output file- bending matrix [``"bending_matrix.dat"``] origin_pdbfile : str (optional) Output file- origin pdb file [``"origin.pdb"``] summary_filename : str (optional) Output file- all of the basic data [``"summary.txt"``] screw_filename : str (optional) Output file- local tilts of individual residues from 2 to n-1 [``"screw.xvg"``] tilt_filename : str (optional) Output file- tilt of line of best fit applied to origin axes [``"local_tilt.xvg"``] bend_filename : str (optional) Output file- local bend angles between successive local helix axes [``"local_bend.xvg"``] twist_filename : str (optional) Output file- local unit twist between successive helix turns [``"unit_twist.xvg"``] prefix : str (optional) Prefix to add to all output file names; set to ``None`` to disable [``"helanal__"``] ref_axis : array_like (optional) Calculate tilt angle relative to the axis; if ``None`` then ``[0,0,1]`` is chosen [``None``] verbose : bool (optional) Toggle diagnostic outputs. [``True``] Raises ------ ValueError If the specified start (begin) time occurs after the end of the trajectory object. If the specified finish time precedes the specified start time or current time stamp of trajectory object. Notes ----- Only a single helix is analyzed. Use the selection to specify the helix, e.g. with "name CA and resid 1:20" or use start=1, stop=20. .. versionchanged:: 0.13.0 New `quiet` keyword to silence frame progress output and most of the output that used to be printed to stdout is now logged to the logger *MDAnalysis.analysis.helanal* (at logelevel *INFO*). .. versionchanged:: 0.16.0 Removed the `start` and `end` keywords for selecting residues because this can be accomplished more transparently with `select`. The first and last resid are directly obtained from the selection. .. deprecated:: 0.16.0 The `quiet` keyword argument is deprecated in favor of the new `verbose` one. .. versionchanged:: 0.20.0 ProgressMeter now iterates over the number of frames analysed. .. versionchanged:: 1.0.0 Changed `selection` keyword to `select` """ if ref_axis is None: ref_axis = np.array([0., 0., 1.]) else: # enable MDA API so that one can use a tuple of atoms or AtomGroup with # two atoms ref_axis = np.asarray(ref_axis) ca = universe.select_atoms(select) start, end = ca.resids[[0, -1]] trajectory = universe.trajectory # Validate user supplied begin / end times traj_end_time = trajectory.ts.time + trajectory.totaltime if begin is not None: if traj_end_time < begin: # Begin occurs after the end of the trajectory, throw error msg = ("The input begin time ({0} ps) occurs after the end " "of the trajectory ({1} ps)".format(begin, traj_end_time)) raise ValueError(msg) elif trajectory.ts.time > begin: # Begin occurs before trajectory start, warn and reset msg = ("The input begin time ({0} ps) precedes the starting " "trajectory time --- Setting starting frame to 0".format( begin)) warnings.warn(msg) logger.warning(msg) start_frame = None else: start_frame = int( np.ceil((begin - trajectory.ts.time) / trajectory.ts.dt)) else: start_frame = None if finish is not None: if (begin is not None) and (begin > finish): # finish occurs before begin time msg = ("The input finish time ({0} ps) precedes the input begin " "time ({1} ps)".format(finish, begin)) raise ValueError(msg) elif trajectory.ts.time > finish: # you'd be starting with a finish time(in ps) that has already # passed or is not available msg = ("The input finish time ({0} ps) precedes the current " "trajectory time ({1} ps)".format(finish, trajectory.time)) raise ValueError(msg) elif traj_end_time < finish: # finish time occurs after the end of trajectory, warn msg = ("The input finish time ({0} ps) occurs after the end of " "the trajectory ({1} ps). Finish time will be set to the " "end of the trajectory".format(finish, traj_end_time)) warnings.warn(msg) logger.warning(msg) end_frame = None else: # To replicate the original behaviour of break when # trajectory.time > finish, we add 1 here. end_frame = int( np.floor((finish - trajectory.ts.time) // trajectory.ts.dt) + 1) else: end_frame = None start_frame, end_frame, frame_step = trajectory.check_slice_indices( start_frame, end_frame, 1) n_frames = len(range(start_frame, end_frame, frame_step)) if start is not None and end is not None: logger.info("Analysing from residue %d to %d", start, end) elif start is not None and end is None: logger.info("Analysing from residue %d to the C termini", start) elif start is None and end is not None: logger.info("Analysing from the N termini to %d", end) logger.info("Analysing %d/%d residues", ca.n_atoms, universe.atoms.n_residues) if prefix is not None: prefix = str(prefix) matrix_filename = prefix + matrix_filename origin_pdbfile = prefix + origin_pdbfile summary_filename = prefix + summary_filename screw_filename = prefix + screw_filename tilt_filename = prefix + tilt_filename fitted_tilt_filename = prefix + fitted_tilt_filename bend_filename = prefix + bend_filename twist_filename = prefix + twist_filename backup_file(matrix_filename) backup_file(origin_pdbfile) backup_file(summary_filename) backup_file(screw_filename) backup_file(tilt_filename) backup_file(fitted_tilt_filename) backup_file(bend_filename) backup_file(twist_filename) global_height = [] global_twist = [] global_rnou = [] global_bending = [] global_bending_matrix = [] global_tilt = [] global_fitted_tilts = [] global_screw = [] for ts in ProgressBar(trajectory[start_frame:end_frame:frame_step], verbose=verbose, desc="Helix analysis"): frame = ts.frame ca_positions = ca.positions twist, bending_angles, height, rnou, origins, local_helix_axes, local_screw_angles = \ main_loop(ca_positions, ref_axis=ref_axis) origin_pdb(origins, origin_pdbfile) #calculate local bending matrix( it is looking at all i, j combinations) if len(global_bending_matrix) == 0: global_bending_matrix = [[[] for item in local_helix_axes] for item in local_helix_axes] for i in range(len(local_helix_axes)): for j in range(i + 1, len(local_helix_axes)): angle = np.rad2deg( np.arccos(np.dot(local_helix_axes[i], local_helix_axes[j]))) global_bending_matrix[i][j].append(angle) #global_bending_matrix[j][i].append(angle) #global_bending_matrix[i][i].append(0.) fit_vector, fit_tilt = vector_of_best_fit(origins) global_height += height global_twist += twist global_rnou += rnou #global_screw.append(local_screw_angles) global_fitted_tilts.append(np.rad2deg(fit_tilt)) #print out rotations across the helix to a file with open(twist_filename, "a") as twist_output: print(frame, end='', file=twist_output) for loc_twist in twist: print(loc_twist, end='', file=twist_output) print("", file=twist_output) with open(bend_filename, "a") as bend_output: print(frame, end='', file=bend_output) for loc_bend in bending_angles: print(loc_bend, end='', file=bend_output) print("", file=bend_output) with open(screw_filename, "a") as rot_output: print(frame, end='', file=rot_output) for rotation in local_screw_angles: print(rotation, end='', file=rot_output) print("", file=rot_output) with open(tilt_filename, "a") as tilt_output: print(frame, end='', file=tilt_output) for tilt in local_helix_axes: print(np.rad2deg(mdamath.angle(tilt, ref_axis)), end='', file=tilt_output) print("", file=tilt_output) with open(fitted_tilt_filename, "a") as tilt_output: print(frame, np.rad2deg(fit_tilt), file=tilt_output) if len(global_bending) == 0: global_bending = [[] for item in bending_angles] #global_tilt = [ [] for item in local_helix_axes ] for store, tmp in zip(global_bending, bending_angles): store.append(tmp) #for store,tmp in zip(global_tilt,local_helix_axes): store.append(mdamath.angle(tmp,ref_axis)) twist_mean, twist_sd, twist_abdev = stats(global_twist) height_mean, height_sd, height_abdev = stats(global_height) rnou_mean, rnou_sd, rnou_abdev = stats(global_rnou) ftilt_mean, ftilt_sd, ftilt_abdev = stats(global_fitted_tilts) bending_statistics = [stats(item) for item in global_bending] #tilt_statistics = [ stats(item) for item in global_tilt] bending_statistics_matrix = [[stats(col) for col in row] for row in global_bending_matrix] with open(matrix_filename, 'w') as mat_output: print("Mean", file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[0]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) print('\nSD', file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[1]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) print("\nABDEV", file=mat_output) for row in bending_statistics_matrix: for col in row: formatted_angle = "{0:6.1f}".format(col[2]) print(formatted_angle, end='', file=mat_output) print('', file=mat_output) logger.info("Height: %g SD: %g ABDEV: %g (Angstroem)", height_mean, height_sd, height_abdev) logger.info("Twist: %g SD: %g ABDEV: %g", twist_mean, twist_sd, twist_abdev) logger.info("Residues/turn: %g SD: %g ABDEV: %g", rnou_mean, rnou_sd, rnou_abdev) logger.info("Fitted tilt: %g SD: %g ABDEV: %g", ftilt_mean, ftilt_sd, ftilt_abdev) logger.info("Local bending angles:") residue_statistics = list(zip(*bending_statistics)) measure_names = ["Mean ", "SD ", "ABDEV"] if start is None: output = " ".join([ "{0:8d}".format(item) for item in range(4, len(residue_statistics[0]) + 4) ]) else: output = " ".join([ "{0:8d}".format(item) for item in range(start + 3, len(residue_statistics[0]) + start + 3) ]) logger.info("ResID %s", output) for measure, name in zip(residue_statistics, measure_names): output = str(name) + " " output += " ".join(["{0:8.1f}".format(residue) for residue in measure]) logger.info(output) with open(summary_filename, 'w') as summary_output: print("Height:", height_mean, "SD", height_sd, "ABDEV", height_abdev, '(nm)', file=summary_output) print("Twist:", twist_mean, "SD", twist_sd, "ABDEV", twist_abdev, file=summary_output) print("Residues/turn:", rnou_mean, "SD", rnou_sd, "ABDEV", rnou_abdev, file=summary_output) print("Local bending angles:", file=summary_output) residue_statistics = list(zip(*bending_statistics)) measure_names = ["Mean ", "SD ", "ABDEV"] print("ResID", end='', file=summary_output) if start is None: for item in range(4, len(residue_statistics[0]) + 4): output = "{0:8d}".format(item) print(output, end='', file=summary_output) else: for item in range(start + 3, len(residue_statistics[0]) + start + 3): output = "{0:8d}".format(item) print(output, end='', file=summary_output) print('', file=summary_output) for measure, name in zip(residue_statistics, measure_names): print(name, end='', file=summary_output) for residue in measure: output = "{0:8.1f}".format(residue) print(output, end='', file=summary_output) print('', file=summary_output)
def testAngleUnitvectors(self): assert_equal(mdamath.angle(self.e1, self.e2), pi / 2) assert_equal(mdamath.angle(self.e1, self.a), pi / 3)
def testAnglePi(self): assert_almost_equal( mdamath.angle(-2.3456e7 * self.e1, 3.4567e-6 * self.e1), np.pi) assert_almost_equal( mdamath.angle(2.3456e7 * self.e1, 3.4567e-6 * self.e1), 0.0)
def _check_AngleRange(self, x): r = 1000. v = r * np.array([np.cos(x), np.sin(x), 0]) assert_almost_equal(mdamath.angle(self.e1, v), x, 6)