def rotation(self, i, motion_index=0): """Set up the rotation for state i.""" # Loop until a valid rotation matrix is found. while True: # The random rotation matrix. R_random_hypersphere(self.R) # Rotation in the eigenframe. R_eigen = dot(transpose(self.axes), dot(self.R, self.axes)) # The angles. phi, theta, sigma = R_to_tilt_torsion(R_eigen) # Skip the rotation if the isotropic cone angle is violated. if theta > self.THETA_Y: continue # Determine theta_max. theta_max = 1.0 / sqrt((cos(phi) / self.THETA_X)**2 + (sin(phi) / self.THETA_Y)**2) # Skip the rotation if the cone angle is violated. if theta > theta_max: continue # Reconstruct the rotation matrix, in the eigenframe, without sigma. tilt_torsion_to_R(phi, theta, 0.0, R_eigen) # Rotate back out of the eigenframe. self.R = dot(self.axes, dot(R_eigen, transpose(self.axes))) # Rotation is ok, so stop looping. break
def rotation_hypersphere_torsionless(self): """Random rotation using 4D hypersphere point picking and return of torsion-tilt angles.""" # Obtain the random torsion-tilt angles from the random hypersphere method. theta, phi, sigma = self.rotation_hypersphere() # Reconstruct a rotation matrix, setting the torsion angle to zero. tilt_torsion_to_R(phi, theta, 0.0, self.rot) # Rotate the frame. self.rot = dot(EIG_FRAME, dot(self.rot, self.eig_frame_T)) # Return the angles. return theta, phi, 0.0
def brownian(file=None, model=None, structure=None, parameters={}, eigenframe=None, pivot=None, atom_id=None, step_size=2.0, snapshot=10, total=1000): """Pseudo-Brownian dynamics simulation of the frame order motions. @keyword file: The opened and writable file object to place the snapshots into. @type file: str @keyword structure: The internal structural object containing the domain to simulate as a single model. @type structure: lib.structure.internal.object.Internal instance @keyword model: The frame order model to simulate. @type model: str @keyword parameters: The dictionary of model parameter values. The key is the parameter name and the value is the value. @type parameters: dict of float @keyword eigenframe: The full 3D eigenframe of the frame order motions. @type eigenframe: numpy rank-2, 3D float64 array @keyword pivot: The list of pivot points of the frame order motions. @type pivot: numpy rank-2 (N, 3) float64 array @keyword atom_id: The atom ID string for the atoms in the structure to rotate - i.e. the moving domain. @type atom_id: None or str @keyword step_size: The rotation will be of a random direction but with this fixed angle. The value is in degrees. @type step_size: float @keyword snapshot: The number of steps in the simulation when snapshots will be taken. @type snapshot: int @keyword total: The total number of snapshots to take before stopping the simulation. @type total: int """ # Check the structural object. if structure.num_models() > 1: raise RelaxError("Only a single model is supported.") # Set the model number. structure.set_model(model_orig=None, model_new=1) # Generate the internal structural selection object. selection = structure.selection(atom_id) # The initial states and motional limits. num_states = len(pivot) states = zeros((num_states, 3, 3), float64) theta_max = [] sigma_max = [] for i in range(num_states): states[i] = eye(3) theta_max.append(None) sigma_max.append(None) # Initialise the rotation matrix data structures. vector = zeros(3, float64) R = eye(3, dtype=float64) step_size = step_size / 360.0 * 2.0 * pi # Axis permutations. perm = [None] if model == MODEL_DOUBLE_ROTOR: perm = [[2, 0, 1], [1, 2, 0]] perm_rev = [[1, 2, 0], [2, 0, 1]] # The maximum cone opening angles (isotropic cones). if 'cone_theta' in parameters: theta_max[0] = parameters['cone_theta'] # The maximum cone opening angles (isotropic cones). theta_x = None theta_y = None if 'cone_theta_x' in parameters: theta_x = parameters['cone_theta_x'] theta_y = parameters['cone_theta_y'] # The maximum torsion angle. if 'cone_sigma_max' in parameters: sigma_max[0] = parameters['cone_sigma_max'] elif 'free rotor' in model: sigma_max[0] = pi # The second torsion angle. if 'cone_sigma_max_2' in parameters: sigma_max[1] = parameters['cone_sigma_max_2'] # Printout. print("\nRunning the simulation:") # Simulate. current_snapshot = 1 step = 1 while True: # End the simulation. if current_snapshot == total: print("\nEnd of simulation.") break # Loop over each state, or motional mode. for i in range(num_states): # The random vector. random_unit_vector(vector) # The rotation matrix. axis_angle_to_R(vector, step_size, R) # Shift the current state. states[i] = dot(R, states[i]) # Rotation in the eigenframe. R_eigen = dot(transpose(eigenframe), dot(states[i], eigenframe)) # Axis permutation to shift each rotation axis to Z. if perm[i] != None: for j in range(3): R_eigen[:, j] = R_eigen[perm[i], j] for j in range(3): R_eigen[j, :] = R_eigen[j, perm[i]] # The angles. phi, theta, sigma = R_to_tilt_torsion(R_eigen) sigma = wrap_angles(sigma, -pi, pi) # Determine theta_max for the pseudo-ellipse models. if theta_x != None: theta_max[i] = 1.0 / sqrt((cos(phi) / theta_x)**2 + (sin(phi) / theta_y)**2) # Set the cone opening angle to the maximum if outside of the limit. if theta_max[i] != None: if theta > theta_max[i]: theta = theta_max[i] # No tilt component. else: theta = 0.0 phi = 0.0 # Set the torsion angle to the maximum if outside of the limits. if sigma_max[i] != None: if sigma > sigma_max[i]: sigma = sigma_max[i] elif sigma < -sigma_max[i]: sigma = -sigma_max[i] else: sigma = 0.0 # Reconstruct the rotation matrix, in the eigenframe, without sigma. tilt_torsion_to_R(phi, theta, sigma, R_eigen) # Reverse axis permutation to shift each rotation z-axis back. if perm[i] != None: for j in range(3): R_eigen[:, j] = R_eigen[perm_rev[i], j] for j in range(3): R_eigen[j, :] = R_eigen[j, perm_rev[i]] # Rotate back out of the eigenframe. states[i] = dot(eigenframe, dot(R_eigen, transpose(eigenframe))) # Take a snapshot. if step == snapshot: # Progress. sys.stdout.write('.') sys.stdout.flush() # Increment the snapshot number. current_snapshot += 1 # Copy the original structural data. structure.add_model(model=current_snapshot, coords_from=1) # Rotate the model. for i in range(num_states): structure.rotate(R=states[i], origin=pivot[i], model=current_snapshot, selection=selection) # Reset the step counter. step = 0 # Increment. step += 1 # Save the result. structure.write_pdb(file=file)
def uniform_distribution(file=None, model=None, structure=None, parameters={}, eigenframe=None, pivot=None, atom_id=None, total=1000, max_rotations=100000): """Uniform distribution of the frame order motions. @keyword file: The opened and writable file object to place the PDB models of the distribution into. @type file: str @keyword structure: The internal structural object containing the domain to distribute as a single model. @type structure: lib.structure.internal.object.Internal instance @keyword model: The frame order model to distribute. @type model: str @keyword parameters: The dictionary of model parameter values. The key is the parameter name and the value is the value. @type parameters: dict of float @keyword eigenframe: The full 3D eigenframe of the frame order motions. @type eigenframe: numpy rank-2, 3D float64 array @keyword pivot: The list of pivot points of the frame order motions. @type pivot: numpy rank-2 (N, 3) float64 array @keyword atom_id: The atom ID string for the atoms in the structure to rotate - i.e. the moving domain. @type atom_id: None or str @keyword total: The total number of states in the distribution. @type total: int @keyword max_rotations: The maximum number of rotations to generate the distribution from. This prevents an execution for an infinite amount of time when a frame order amplitude parameter is close to zero so that the subset of all rotations within the distribution is close to zero. @type max_rotations: int """ # Check the structural object. if structure.num_models() > 1: raise RelaxError("Only a single model is supported.") # Set the model number. structure.set_model(model_orig=None, model_new=1) # Generate the internal structural selection object. selection = structure.selection(atom_id) # The initial states and motional limits. num_states = len(pivot) states = zeros((num_states, 3, 3), float64) theta_max = [] sigma_max = [] for i in range(num_states): states[i] = eye(3) theta_max.append(None) sigma_max.append(None) # Initialise the rotation matrix data structures. R = eye(3, dtype=float64) # Axis permutations. perm = [None] if model == MODEL_DOUBLE_ROTOR: perm = [[2, 0, 1], [1, 2, 0]] perm_rev = [[1, 2, 0], [2, 0, 1]] # The maximum cone opening angles (isotropic cones). if 'cone_theta' in parameters: theta_max[0] = parameters['cone_theta'] # The maximum cone opening angles (isotropic cones). theta_x = None theta_y = None if 'cone_theta_x' in parameters: theta_x = parameters['cone_theta_x'] theta_y = parameters['cone_theta_y'] # The maximum torsion angle. if 'cone_sigma_max' in parameters: sigma_max[0] = parameters['cone_sigma_max'] elif 'free rotor' in model: sigma_max[0] = pi # The second torsion angle. if 'cone_sigma_max_2' in parameters: sigma_max[1] = parameters['cone_sigma_max_2'] # Printout. print("\nGenerating the distribution:") # Distribution. current_state = 1 num = -1 while True: # The total number of rotations. num += 1 # End. if current_state == total: break if num >= max_rotations: sys.stdout.write('\n') warn( RelaxWarning( "Maximum number of rotations encountered - the distribution only contains %i states." % current_state)) break # Loop over each state, or motional mode. inside = True for i in range(num_states): # The random rotation matrix. R_random_hypersphere(R) # Shift the current state. states[i] = dot(R, states[i]) # Rotation in the eigenframe. R_eigen = dot(transpose(eigenframe), dot(states[i], eigenframe)) # Axis permutation to shift each rotation axis to Z. if perm[i] != None: for j in range(3): R_eigen[:, j] = R_eigen[perm[i], j] for j in range(3): R_eigen[j, :] = R_eigen[j, perm[i]] # The angles. phi, theta, sigma = R_to_tilt_torsion(R_eigen) sigma = wrap_angles(sigma, -pi, pi) # Determine theta_max for the pseudo-ellipse models. if theta_x != None: theta_max[i] = 1.0 / sqrt((cos(phi) / theta_x)**2 + (sin(phi) / theta_y)**2) # The cone opening angle is outside of the limit. if theta_max[i] != None: if theta > theta_max[i]: inside = False # No tilt component. else: theta = 0.0 phi = 0.0 # The torsion angle is outside of the limits. if sigma_max[i] != None: if sigma > sigma_max[i]: inside = False elif sigma < -sigma_max[i]: inside = False else: sigma = 0.0 # Reconstruct the rotation matrix, in the eigenframe, without sigma. tilt_torsion_to_R(phi, theta, sigma, R_eigen) # Reverse axis permutation to shift each rotation z-axis back. if perm[i] != None: for j in range(3): R_eigen[:, j] = R_eigen[perm_rev[i], j] for j in range(3): R_eigen[j, :] = R_eigen[j, perm_rev[i]] # Rotate back out of the eigenframe. states[i] = dot(eigenframe, dot(R_eigen, transpose(eigenframe))) # The state is outside of the distribution. if not inside: continue # Progress. sys.stdout.write('.') sys.stdout.flush() # Increment the snapshot number. current_state += 1 # Copy the original structural data. structure.add_model(model=current_state, coords_from=1) # Rotate the model. for i in range(num_states): structure.rotate(R=states[i], origin=pivot[i], model=current_state, selection=selection) # Save the result. structure.write_pdb(file=file)
def pcs_pivot_motion_full_qrint(theta_i=None, phi_i=None, sigma_i=None, full_in_ref_frame=None, r_pivot_atom=None, r_pivot_atom_rev=None, r_ln_pivot=None, A=None, R_eigen=None, RT_eigen=None, Ri_prime=None, pcs_theta=None, pcs_theta_err=None, missing_pcs=None, error_flag=False): """Calculate the PCS value after a pivoted motion for the isotropic cone model. @keyword theta_i: The half cone opening angle (polar angle). @type theta_i: float @keyword phi_i: The cone azimuthal angle. @type phi_i: float @keyword sigma_i: The torsion angle for state i. @type sigma_i: float @keyword full_in_ref_frame: An array of flags specifying if the tensor in the reference frame is the full or reduced tensor. @type full_in_ref_frame: numpy rank-1 array @keyword r_pivot_atom: The pivot point to atom vector. @type r_pivot_atom: numpy rank-2, 3D array @keyword r_pivot_atom_rev: The reversed pivot point to atom vector. @type r_pivot_atom_rev: numpy rank-2, 3D array @keyword r_ln_pivot: The lanthanide position to pivot point vector. @type r_ln_pivot: numpy rank-2, 3D array @keyword A: The full alignment tensor of the non-moving domain. @type A: numpy rank-2, 3D array @keyword R_eigen: The eigenframe rotation matrix. @type R_eigen: numpy rank-2, 3D array @keyword RT_eigen: The transpose of the eigenframe rotation matrix (for faster calculations). @type RT_eigen: numpy rank-2, 3D array @keyword Ri_prime: The empty rotation matrix for the in-frame isotropic cone motion for state i. @type Ri_prime: numpy rank-2, 3D array @keyword pcs_theta: The storage structure for the back-calculated PCS values. @type pcs_theta: numpy rank-2 array @keyword pcs_theta_err: The storage structure for the back-calculated PCS errors. @type pcs_theta_err: numpy rank-2 array @keyword missing_pcs: A structure used to indicate which PCS values are missing. @type missing_pcs: numpy rank-2 array @keyword error_flag: A flag which if True will cause the PCS errors to be estimated and stored in pcs_theta_err. @type error_flag: bool """ # The rotation matrix. tilt_torsion_to_R(phi_i, theta_i, sigma_i, Ri_prime) # The rotation. R_i = dot(R_eigen, dot(Ri_prime, RT_eigen)) # Pre-calculate all the new vectors (forwards and reverse). rot_vect_rev = transpose(dot(R_i, r_pivot_atom_rev) + r_ln_pivot) rot_vect = transpose(dot(R_i, r_pivot_atom) + r_ln_pivot) # Loop over the atoms. for j in range(len(r_pivot_atom[0])): # The vector length (to the 5th power). length_rev = 1.0 / sqrt(inner(rot_vect_rev[j], rot_vect_rev[j]))**5 length = 1.0 / sqrt(inner(rot_vect[j], rot_vect[j]))**5 # Loop over the alignments. for i in range(len(pcs_theta)): # Skip missing data. if missing_pcs[i, j]: continue # The projection. if full_in_ref_frame[i]: proj = dot(rot_vect[j], dot(A[i], rot_vect[j])) length_i = length else: proj = dot(rot_vect_rev[j], dot(A[i], rot_vect_rev[j])) length_i = length_rev # The PCS. pcs_theta[i, j] += proj * length_i # The square. if error_flag: pcs_theta_err[i, j] += (proj * length_i)**2
def uniform_distribution(file=None, model=None, structure=None, parameters={}, eigenframe=None, pivot=None, atom_id=None, total=1000, max_rotations=100000): """Uniform distribution of the frame order motions. @keyword file: The opened and writable file object to place the PDB models of the distribution into. @type file: str @keyword structure: The internal structural object containing the domain to distribute as a single model. @type structure: lib.structure.internal.object.Internal instance @keyword model: The frame order model to distribute. @type model: str @keyword parameters: The dictionary of model parameter values. The key is the parameter name and the value is the value. @type parameters: dict of float @keyword eigenframe: The full 3D eigenframe of the frame order motions. @type eigenframe: numpy rank-2, 3D float64 array @keyword pivot: The list of pivot points of the frame order motions. @type pivot: numpy rank-2 (N, 3) float64 array @keyword atom_id: The atom ID string for the atoms in the structure to rotate - i.e. the moving domain. @type atom_id: None or str @keyword total: The total number of states in the distribution. @type total: int @keyword max_rotations: The maximum number of rotations to generate the distribution from. This prevents an execution for an infinite amount of time when a frame order amplitude parameter is close to zero so that the subset of all rotations within the distribution is close to zero. @type max_rotations: int """ # Check the structural object. if structure.num_models() > 1: raise RelaxError("Only a single model is supported.") # Set the model number. structure.set_model(model_orig=None, model_new=1) # Generate the internal structural selection object. selection = structure.selection(atom_id) # The initial states and motional limits. num_states = len(pivot) states = zeros((num_states, 3, 3), float64) theta_max = [] sigma_max = [] for i in range(num_states): states[i] = eye(3) theta_max.append(None) sigma_max.append(None) # Initialise the rotation matrix data structures. R = eye(3, dtype=float64) # Axis permutations. perm = [None] if model == MODEL_DOUBLE_ROTOR: perm = [[2, 0, 1], [1, 2, 0]] perm_rev = [[1, 2, 0], [2, 0, 1]] # The maximum cone opening angles (isotropic cones). if 'cone_theta' in parameters: theta_max[0] = parameters['cone_theta'] # The maximum cone opening angles (isotropic cones). theta_x = None theta_y = None if 'cone_theta_x' in parameters: theta_x = parameters['cone_theta_x'] theta_y = parameters['cone_theta_y'] # The maximum torsion angle. if 'cone_sigma_max' in parameters: sigma_max[0] = parameters['cone_sigma_max'] elif 'free rotor' in model: sigma_max[0] = pi # The second torsion angle. if 'cone_sigma_max_2' in parameters: sigma_max[1] = parameters['cone_sigma_max_2'] # Printout. print("\nGenerating the distribution:") # Distribution. current_state = 1 num = -1 while True: # The total number of rotations. num += 1 # End. if current_state == total: break if num >= max_rotations: sys.stdout.write('\n') warn(RelaxWarning("Maximum number of rotations encountered - the distribution only contains %i states." % current_state)) break # Loop over each state, or motional mode. inside = True for i in range(num_states): # The random rotation matrix. R_random_hypersphere(R) # Shift the current state. states[i] = dot(R, states[i]) # Rotation in the eigenframe. R_eigen = dot(transpose(eigenframe), dot(states[i], eigenframe)) # Axis permutation to shift each rotation axis to Z. if perm[i] != None: for j in range(3): R_eigen[:, j] = R_eigen[perm[i], j] for j in range(3): R_eigen[j, :] = R_eigen[j, perm[i]] # The angles. phi, theta, sigma = R_to_tilt_torsion(R_eigen) sigma = wrap_angles(sigma, -pi, pi) # Determine theta_max for the pseudo-ellipse models. if theta_x != None: theta_max[i] = 1.0 / sqrt((cos(phi) / theta_x)**2 + (sin(phi) / theta_y)**2) # The cone opening angle is outside of the limit. if theta_max[i] != None: if theta > theta_max[i]: inside = False # No tilt component. else: theta = 0.0 phi = 0.0 # The torsion angle is outside of the limits. if sigma_max[i] != None: if sigma > sigma_max[i]: inside = False elif sigma < -sigma_max[i]: inside = False else: sigma = 0.0 # Reconstruct the rotation matrix, in the eigenframe, without sigma. tilt_torsion_to_R(phi, theta, sigma, R_eigen) # Reverse axis permutation to shift each rotation z-axis back. if perm[i] != None: for j in range(3): R_eigen[:, j] = R_eigen[perm_rev[i], j] for j in range(3): R_eigen[j, :] = R_eigen[j, perm_rev[i]] # Rotate back out of the eigenframe. states[i] = dot(eigenframe, dot(R_eigen, transpose(eigenframe))) # The state is outside of the distribution. if not inside: continue # Progress. sys.stdout.write('.') sys.stdout.flush() # Increment the snapshot number. current_state += 1 # Copy the original structural data. structure.add_model(model=current_state, coords_from=1) # Rotate the model. for i in range(num_states): structure.rotate(R=states[i], origin=pivot[i], model=current_state, selection=selection) # Save the result. structure.write_pdb(file=file)