def print_axis_system_full(self): """Print out of the full system to file.""" # Open the file. file = open(self.save_path+sep+'axis_system', 'w') # Header. file.write("\n") file.write("The motional axis system\n") file.write("========================\n") # The full axis system. file.write("\nThe full axis system:\n") string = '' for i in range(3): string += '[' for j in range(3): string += "%24.20f" % self.axes[i, j] string += ']\n' file.write(string) # The Euler angles. a, b, g = R_to_euler_zyz(self.axes) file.write("\nEuler angles of the system:\n") file.write(" alpha: %.20f\n" % a) file.write(" beta: %.20f\n" % b) file.write(" gamma: %.20f\n" % g) # The spherical angle system. r, t, p = cartesian_to_spherical(self.axes[:, 2]) file.write("\nSpherical angles of the z-axis:\n") file.write(" theta: %.20f\n" % t) file.write(" phi: %.20f\n" % wrap_angles(p, 0, 2*pi))
def eigen_system(): """Recreate the eigensystem parameters.""" # The centre of masses of each domain (from the system_create.log file). N_COM = array([41.739, 6.03, -0.764], float64) C_COM = array([26.837, -12.379, 28.342], float64) # The Z-axis as the inter CoM vector. z_axis = C_COM - N_COM disp = norm(z_axis) z_axis /= disp # The eigenframe (partly from the system_create.log file). eigensystem = transpose( array([[ -7.778375610280605e-01, 6.284649244351433e-01, -7.532653237683726e-04 ], [-0.487095774865268, -0.60362450312215, -0.63116968030708], z_axis], float64)) # Convert to Euler angles. a, b, g = R_to_euler_zyz(eigensystem) # Return the parameters. return a, b, g, disp
def calc_euler(rotation): """Calculate the zyz notation Euler angles. @param rotation: The rotation matrix. @type rotation: numpy 3D, rank-2 array @return: The Euler angles alpha, beta, and gamma in zyz notation. @rtype: tuple of float """ return R_to_euler_zyz(rotation)
def tensor_eigen_system(tensor): """Determine the eigenvalues and vectors for the tensor, sorting the entries. @return: The eigenvalues, rotation matrix, and the Euler angles in zyz notation. @rtype: 3D rank-1 array, 3D rank-2 array, float, float, float """ # Eigenvalues. R, Di, A = svd(tensor) D_diag = zeros((3, 3), float64) for i in range(3): D_diag[i, i] = Di[i] # Reordering structure. reorder_data = [] for i in range(3): reorder_data.append([Di[i], i]) reorder_data.sort() # The indices. reorder = zeros(3, int) Di_sort = zeros(3, float) for i in range(3): Di_sort[i], reorder[i] = reorder_data[i] # Reorder columns. R_new = zeros((3, 3), float64) for i in range(3): R_new[:, i] = R[:, reorder[i]] # Switch from the left handed to right handed universes (if needed). if norm(cross(R_new[:, 0], R_new[:, 1]) - R_new[:, 2]) > 1e-7: R_new[:, 2] = -R_new[:, 2] # Reverse the rotation. R_new = transpose(R_new) # Euler angles (reverse rotation in the rotated axis system). gamma, beta, alpha = R_to_euler_zyz(R_new) # Collapse the pi axis rotation symmetries. if alpha >= pi: alpha = alpha - pi if gamma >= pi: alpha = pi - alpha beta = pi - beta gamma = gamma - pi if beta >= pi: alpha = pi - alpha beta = beta - pi # Return the values. return Di_sort, R_new, alpha, beta, gamma
def rotation_hypersphere(self): """Random rotation using 4D hypersphere point picking and return of torsion-tilt angles.""" # Generate a random rotation. R_random_hypersphere(self.rot) # Rotate the frame. frame = dot(self.eig_frame_T, dot(self.rot, EIG_FRAME)) # Decompose the frame into the zyz Euler angles. alpha, beta, gamma = R_to_euler_zyz(frame) # Convert to tilt and torsion angles (properly wrapped) and return them. theta = beta phi = wrap_angles(gamma, -pi, pi) sigma = wrap_angles(alpha + gamma, -pi, pi) return theta, phi, sigma
def rotation_z_axis(self): """Random rotation around the z-axis and return of torsion-tilt angles""" # Random angle between -pi and pi. angle = uniform(-pi, pi) # Generate the rotation matrix. axis_angle_to_R(self.z_axis, angle, self.rot) # Decompose the rotation into the zyz Euler angles. alpha, beta, gamma = R_to_euler_zyz(self.rot) # Rotate the frame. self.rot = dot(EIG_FRAME, dot(self.rot, self.eig_frame_T)) # Convert to tilt and torsion angles (properly wrapped) and return them. theta = beta phi = wrap_angles(gamma, -pi, pi) sigma = wrap_angles(alpha + gamma, -pi, pi) return theta, phi, sigma
def build_axes_pivot_com(self): """A standard axis system for the CaM system with the z-axis along the pivot-com axis.""" # The z-axis for the rotations (the pivot point to CoM axis). axis_z = self.COM - self.PIVOT axis_z = axis_z / norm(axis_z) # The y-axis (to check the torsion angle). axis_y = cross(axis_z, array([0, 0, 1])) axis_y = axis_y / norm(axis_y) # The x-axis. axis_x = cross(axis_y, axis_z) axis_x = axis_x / norm(axis_x) # The eigenframe. self.axes = transpose(array([axis_x, axis_y, axis_z])) alpha, beta, gamma = R_to_euler_zyz(self.axes) # Printout. print("CoM-pivot axis: %s, norm = %s" % (repr(axis_z), norm(axis_z))) print("Rotation axis: %s, norm = %s" % (repr(self.axes[:, 2]), norm(self.axes[:, 2]))) print("Full axis system:\n%s" % self.axes) print("Full axis system Euler angles:\n\talpha: %s\n\tbeta: %s\n\tgamma: %s" % (repr(alpha), repr(beta), repr(gamma)))
def build_axes_alt(self): """An alternative axis system for the CaM system.""" # The z-axis for the rotations (the pivot point to CoM axis). axis_z = self.COM - self.PIVOT axis_z = axis_z / norm(axis_z) # The y-axis (to check the torsion angle). axis_y = cross(axis_z, array([0, 0, 1])) axis_y = axis_y / norm(axis_y) # The x-axis. axis_x = cross(axis_y, axis_z) axis_x = axis_x / norm(axis_x) # The eigenframe. axes = transpose(array([axis_x, axis_y, axis_z])) # Init a rotation matrix. R = zeros((3, 3), float64) # Tilt the axes system by x degrees. tilt_axis = cross(axis_z, array([0, 0, 1])) tilt_axis = tilt_axis / norm(tilt_axis) axis_angle_to_R(tilt_axis, self.TILT_ANGLE * 2.0 * pi / 360.0, R) # Rotate the eigenframe. self.axes = dot(R, axes) alpha, beta, gamma = R_to_euler_zyz(self.axes) # Printout. print("Tilt axis: %s, norm = %s" % (repr(tilt_axis), norm(tilt_axis))) print("CoM-pivot axis: %s, norm = %s" % (repr(axis_z), norm(axis_z))) print("Rotation axis: %s, norm = %s" % (repr(self.axes[:, 2]), norm(self.axes[:, 2]))) print("Full axis system:\n%s" % self.axes) print("Full axis system Euler angles:\n\talpha: %s\n\tbeta: %s\n\tgamma: %s" % (repr(alpha), repr(beta), repr(gamma)))
def kabsch(name_from=None, name_to=None, coord_from=None, coord_to=None, centre_type="centroid", elements=None, centroid=None, verbosity=1): """Calculate the rotational and translational displacements between the two given coordinate sets. This uses the U{Kabsch algorithm<http://en.wikipedia.org/wiki/Kabsch_algorithm>}. @keyword name_from: The name of the starting structure, used for the printouts. @type name_from: str @keyword name_to: The name of the ending structure, used for the printouts. @type name_to: str @keyword coord_from: The list of atomic coordinates for the starting structure. @type coord_from: numpy rank-2, Nx3 array @keyword coord_to: The list of atomic coordinates for the ending structure. @type coord_to: numpy rank-2, Nx3 array @keyword centre_type: The type of centre to superimpose over. This can either be the standard centroid superimposition or the CoM could be used instead. @type centre_type: str @keyword elements: The list of elements corresponding to the atoms. @type elements: list of str @keyword centroid: An alternative position of the centroid, used for studying pivoted systems. @type centroid: list of float or numpy rank-1, 3D array @return: The translation vector T, translation distance d, rotation matrix R, rotation axis r, rotation angle theta, and the rotational pivot defined as the centroid of the ending structure. @rtype: numpy rank-1 3D array, float, numpy rank-2 3D array, numpy rank-1 3D array, float, numpy rank-1 3D array """ # Calculate the centroids. if centroid is not None: centroid_from = centroid centroid_to = centroid elif centre_type == 'centroid': centroid_from = find_centroid(coord_from) centroid_to = find_centroid(coord_to) else: centroid_from, mass_from = centre_of_mass(pos=coord_from, elements=elements) centroid_to, mass_to = centre_of_mass(pos=coord_to, elements=elements) # The translation. trans_vect = centroid_to - centroid_from trans_dist = norm(trans_vect) # Calculate the rotation. R = kabsch_rotation(coord_from=coord_from, coord_to=coord_to, centroid_from=centroid_from, centroid_to=centroid_to) axis, angle = R_to_axis_angle(R) a, b, g = R_to_euler_zyz(R) # Print out. if verbosity >= 1: print( "\n\nCalculating the rotational and translational displacements from %s to %s using the Kabsch algorithm.\n" % (name_from, name_to)) if centre_type == 'centroid': print("Start centroid: [%20.15f, %20.15f, %20.15f]" % (centroid_from[0], centroid_from[1], centroid_from[2])) print("End centroid: [%20.15f, %20.15f, %20.15f]" % (centroid_to[0], centroid_to[1], centroid_to[2])) else: print("Start CoM: [%20.15f, %20.15f, %20.15f]" % (centroid_from[0], centroid_from[1], centroid_from[2])) print("End CoM: [%20.15f, %20.15f, %20.15f]" % (centroid_to[0], centroid_to[1], centroid_to[2])) print("Translation vector: [%20.15f, %20.15f, %20.15f]" % (trans_vect[0], trans_vect[1], trans_vect[2])) print("Translation distance: %.15f" % trans_dist) print("Rotation matrix:") print(" [[%20.15f, %20.15f, %20.15f]" % (R[0, 0], R[0, 1], R[0, 2])) print(" [%20.15f, %20.15f, %20.15f]" % (R[1, 0], R[1, 1], R[1, 2])) print(" [%20.15f, %20.15f, %20.15f]]" % (R[2, 0], R[2, 1], R[2, 2])) print("Rotation axis: [%20.15f, %20.15f, %20.15f]" % (axis[0], axis[1], axis[2])) print("Rotation euler angles: [%20.15f, %20.15f, %20.15f]" % (a, b, g)) print("Rotation angle (deg): %.15f" % (angle / 2.0 / pi * 360.0)) # Return the data. return trans_vect, trans_dist, R, axis, angle, centroid_to
def permute_axes(permutation='A'): """Permute the axes of the motional eigenframe to switch between local minima. @keyword permutation: The permutation to use. This can be either 'A' or 'B' to select between the 3 permutations, excluding the current combination. @type permutation: str """ # Check that the model is valid. allowed = MODEL_LIST_ISO_CONE + MODEL_LIST_PSEUDO_ELLIPSE if cdp.model not in allowed: raise RelaxError( "The permutation of the motional eigenframe is only valid for the frame order models %s." % allowed) # Check that the model parameters are setup. if cdp.model in MODEL_LIST_ISO_CONE: if not hasattr(cdp, 'cone_theta') or not is_float(cdp.cone_theta): raise RelaxError("The parameter values are not set up.") else: if not hasattr(cdp, 'cone_theta_y') or not is_float(cdp.cone_theta_y): raise RelaxError("The parameter values are not set up.") # The iso cones only have one permutation. if cdp.model in MODEL_LIST_ISO_CONE and permutation == 'B': raise RelaxError("The isotropic cones only have one permutation.") # The angles. cone_sigma_max = 0.0 if cdp.model in MODEL_LIST_RESTRICTED_TORSION: cone_sigma_max = cdp.cone_sigma_max elif cdp.model in MODEL_LIST_FREE_ROTORS: cone_sigma_max = pi if cdp.model in MODEL_LIST_ISO_CONE: angles = array([cdp.cone_theta, cdp.cone_theta, cone_sigma_max], float64) else: angles = array([cdp.cone_theta_x, cdp.cone_theta_y, cone_sigma_max], float64) x, y, z = angles # The axis system. axes = generate_axis_system() # Start printout for the isotropic cones. if cdp.model in MODEL_LIST_ISO_CONE: print("\nOriginal parameters:") print("%-20s %20.10f" % ("cone_theta", cdp.cone_theta)) print("%-20s %20.10f" % ("cone_sigma_max", cone_sigma_max)) print("%-20s %20.10f" % ("axis_theta", cdp.axis_theta)) print("%-20s %20.10f" % ("axis_phi", cdp.axis_phi)) print("%-20s\n%s" % ("cone axis", axes[:, 2])) print("%-20s\n%s" % ("full axis system", axes)) print("\nPermutation '%s':" % permutation) # Start printout for the pseudo-ellipses. else: print("\nOriginal parameters:") print("%-20s %20.10f" % ("cone_theta_x", cdp.cone_theta_x)) print("%-20s %20.10f" % ("cone_theta_y", cdp.cone_theta_y)) print("%-20s %20.10f" % ("cone_sigma_max", cone_sigma_max)) print("%-20s %20.10f" % ("eigen_alpha", cdp.eigen_alpha)) print("%-20s %20.10f" % ("eigen_beta", cdp.eigen_beta)) print("%-20s %20.10f" % ("eigen_gamma", cdp.eigen_gamma)) print("%-20s\n%s" % ("eigenframe", axes)) print("\nPermutation '%s':" % permutation) # The axis inversion structure. inv = ones(3, float64) # The starting condition x <= y <= z. if x <= y and y <= z: # Printout. print("%-20s %-20s" % ("Starting condition", "x <= y <= z")) # The cone angle and axes permutations. if permutation == 'A': perm_angles = [0, 2, 1] perm_axes = [2, 1, 0] inv[perm_axes[2]] = -1.0 else: perm_angles = [1, 2, 0] perm_axes = [2, 0, 1] # The starting condition x <= z <= y. elif x <= z and z <= y: # Printout. print("%-20s %-20s" % ("Starting condition", "x <= z <= y")) # The cone angle and axes permutations. if permutation == 'A': perm_angles = [0, 2, 1] perm_axes = [2, 1, 0] inv[perm_axes[2]] = -1.0 else: perm_angles = [2, 1, 0] perm_axes = [0, 2, 1] inv[perm_axes[2]] = -1.0 # The starting condition z <= x <= y. elif z <= x and x <= y: # Printout. print("%-20s %-20s" % ("Starting condition", "z <= x <= y")) # The cone angle and axes permutations. if permutation == 'A': perm_angles = [2, 0, 1] perm_axes = [1, 2, 0] else: perm_angles = [2, 1, 0] perm_axes = [0, 2, 1] inv[perm_axes[2]] = -1.0 # Cannot be here. else: raise RelaxFault # Printout. print("%-20s %-20s" % ("Cone angle permutation", perm_angles)) print("%-20s %-20s" % ("Axes permutation", perm_axes)) # Permute the angles. if cdp.model in MODEL_LIST_ISO_CONE: cdp.cone_theta = (angles[perm_angles[0]] + angles[perm_angles[1]]) / 2.0 else: cdp.cone_theta_x = angles[perm_angles[0]] cdp.cone_theta_y = angles[perm_angles[1]] if cdp.model in MODEL_LIST_RESTRICTED_TORSION: cdp.cone_sigma_max = angles[perm_angles[2]] elif cdp.model in MODEL_LIST_FREE_ROTORS: cdp.cone_sigma_max = pi # Permute the axes (iso cone). if cdp.model in MODEL_LIST_ISO_CONE: # Convert the y-axis to spherical coordinates (the x-axis would be ok too, or any vector in the x-y plane due to symmetry of the original permutation). axis_new = axes[:, 1] r, cdp.axis_theta, cdp.axis_phi = cartesian_to_spherical(axis_new) # Permute the axes (pseudo-ellipses). else: axes_new = transpose( array([ inv[0] * axes[:, perm_axes[0]], inv[1] * axes[:, perm_axes[1]], inv[2] * axes[:, perm_axes[2]] ], float64)) # Convert the permuted frame to Euler angles and store them. cdp.eigen_alpha, cdp.eigen_beta, cdp.eigen_gamma = R_to_euler_zyz( axes_new) # End printout. if cdp.model in MODEL_LIST_ISO_CONE: print("\nPermuted parameters:") print("%-20s %20.10f" % ("cone_theta", cdp.cone_theta)) if cdp.model == MODEL_ISO_CONE: print("%-20s %20.10f" % ("cone_sigma_max", cdp.cone_sigma_max)) print("%-20s %20.10f" % ("axis_theta", cdp.axis_theta)) print("%-20s %20.10f" % ("axis_phi", cdp.axis_phi)) print("%-20s\n%s" % ("cone axis", axis_new)) else: print("\nPermuted parameters:") print("%-20s %20.10f" % ("cone_theta_x", cdp.cone_theta_x)) print("%-20s %20.10f" % ("cone_theta_y", cdp.cone_theta_y)) if cdp.model == MODEL_PSEUDO_ELLIPSE: print("%-20s %20.10f" % ("cone_sigma_max", cdp.cone_sigma_max)) print("%-20s %20.10f" % ("eigen_alpha", cdp.eigen_alpha)) print("%-20s %20.10f" % ("eigen_beta", cdp.eigen_beta)) print("%-20s %20.10f" % ("eigen_gamma", cdp.eigen_gamma)) print("%-20s\n%s" % ("eigenframe", axes_new))
CONE_SIGMA_MAX = 30.0 / 360.0 * 2.0 * pi # Reconstruct the rotation axis. AXIS = zeros(3, float64) spherical_to_cartesian([1, AXIS_THETA, AXIS_PHI], AXIS) # Create a full normalised axis system. x = array([1, 0, 0], float64) y = cross(AXIS, x) y /= norm(y) x = cross(y, AXIS) x /= norm(x) AXES = transpose(array([x, y, AXIS], float64)) # The Euler angles. eigen_alpha, eigen_beta, eigen_gamma = R_to_euler_zyz(AXES) # Printout. print("Torsion angle: %s" % CONE_SIGMA_MAX) print("Rotation axis: %s" % AXIS) print("Full axis system:\n%s" % AXES) print("cross(x, y) = z:\n %s = %s" % (cross(AXES[:, 0], AXES[:, 1]), AXES[:, 2])) print("cross(x, z) = -y:\n %s = %s" % (cross(AXES[:, 0], AXES[:, 2]), -AXES[:, 1])) print("cross(y, z) = x:\n %s = %s" % (cross(AXES[:, 1], AXES[:, 2]), AXES[:, 0])) print("Euler angles (alpha, beta, gamma): (%.15f, %.15f, %.15f)" % (eigen_alpha, eigen_beta, eigen_gamma)) # Load the optimised rotor state for creating the pseudo-ellipse data pipes. state.load(state='frame_order_true', dir='..') # Set up the dynamic system. value.set(param='ave_pos_x', val=AVE_POS_X)
def _calculate_rdc(self): """Calculate the averaged RDC for all states.""" # Open the output files. if self.ROT_FILE: rot_file = open_write_file('rotations', dir=self.save_path, compress_type=1, force=True) # Printout. sys.stdout.write("\n\nRotating %s states for the RDC:\n\n" % locale.format("%d", self.N**self.MODES, grouping=True)) # Turn off the relax interpreter echoing to allow the progress meter to be shown correctly. self.interpreter.off() # Set up some data structures for faster calculations. interatoms = [] vectors = [] d = [] for interatom in interatomic_loop(): # Nothing to do. if not hasattr(interatom, 'vector'): continue # Initialise the RDC structure (as a 1D numpy.float128 array for speed and minimising truncation artifacts). interatom.rdc = {} for tag in self._tensors: interatom.rdc[tag] = zeros(1, float128) # Pack the interatomic containers and vectors. interatoms.append(interatom) vectors.append(interatom.vector) # Get the spins. spin1 = return_spin(spin_id=interatom.spin_id1) spin2 = return_spin(spin_id=interatom.spin_id2) # Gyromagnetic ratios. g1 = periodic_table.gyromagnetic_ratio(spin1.isotope) g2 = periodic_table.gyromagnetic_ratio(spin2.isotope) # Calculate the RDC dipolar constant (in Hertz, and the 3 comes from the alignment tensor), and append it to the list. d.append(3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r)) # Repackage the data for speed. vectors = transpose(array(vectors, float64)) d = array(d, float64) num_interatoms = len(vectors) # Store the alignment tensors. A = [] for i in range(len(self._tensors)): A.append(cdp.align_tensors[i].A) # Loop over each position. for global_index, mode_indices in self._state_loop(): # The progress meter. self._progress(global_index) # Total rotation matrix (for construction of the frame order matrix). total_R = eye(3) # Data initialisation. new_vect = vectors # Loop over each motional mode. for motion_index in range(self.MODES): # Generate the distribution specific rotation. self.rotation(mode_indices[motion_index], motion_index=motion_index) # Rotate the NH vector. new_vect = dot(self.R, new_vect) # Decompose the rotation into Euler angles and store them. if self.ROT_FILE: a, b, g = R_to_euler_zyz(self.R) rot_file.write('Mode %i: %10.7f %10.7f %10.7f\n' % (motion_index, a, b, g)) # Contribution to the total rotation. total_R = dot(self.R, total_R) # Loop over each alignment. for i in range(len(self._tensors)): # Calculate the RDC as quickly as possible. rdcs = d * tensordot(transpose(new_vect), tensordot(A[i], new_vect, axes=1), axes=1) # Store the values. for j in range(len(interatoms)): interatoms[j].rdc[self._tensors[i]][0] += rdcs[j, j] # The frame order matrix component. self.daeg += kron_prod(total_R, total_R) # Print out. sys.stdout.write('\n\n') # Frame order matrix averaging. self.daeg = self.daeg / self.N**self.MODES # Write out the frame order matrix. file = open(self.save_path+sep+'frame_order_matrix', 'w') print_frame_order_2nd_degree(self.daeg, file=file, places=8) # Reactive the interpreter echoing. self.interpreter.on() # Average the RDC and write the data. for tag in self._tensors: # Average. for interatom in interatomic_loop(): interatom.rdc[tag] = interatom.rdc[tag][0] / self.N**self.MODES # Save. self.interpreter.rdc.write(align_id=tag, file='rdc_%s.txt'%tag, dir=self.save_path, force=True)
# Python module imports. from numpy import array, float64, transpose, zeros # relax module imports. from lib.geometry.rotations import euler_to_R_zyz, R_to_euler_zyz # Create a data pipe for the data. pipe.create('displace', 'N-state') # Load the structure. structure.read_pdb('fancy_mol.pdb') # First rotate. R = zeros((3, 3), float64) euler_to_R_zyz(1, 2, 3, R) origin = array([1, 1, 1], float64) structure.rotate(R=R, origin=origin) # Then translate. T = array([1, 2, 3], float64) structure.translate(T=T) # Write out the new structure. structure.write_pdb('displaced.pdb', force=True) # Printout of the inverted Euler angles of rotation (the solution). a, b, g = R_to_euler_zyz(transpose(R)) print("alpha: %s" % a) print("beta: %s" % b) print("gamma: %s" % g)