def rotate_global(self, element, axis, angle, reverse=False, glob=True): if self.positions: x, y, z = np.asarray(nostrom(axis)) / (np.linalg.norm( np.asarray(nostrom(axis)))) phi_2 = angle / 2. pos = self.positions[:] starting_index = 1 if glob: starting_index = 0 ##print(element) if reverse: shift_forward = mm.Vec3(0, 0, 0) * unit.angstroms - pos[element[2]] else: shift_forward = mm.Vec3( 0, 0, 0) * unit.angstroms - pos[element[starting_index]] s = np.math.sin(phi_2) c = np.math.cos(phi_2) rot = np.array([[ 2 * (np.power(x, 2) - 1) * np.power(s, 2) + 1, 2 * x * y * np.power(s, 2) - 2 * z * c * s, 2 * x * z * np.power(s, 2) + 2 * y * c * s ], [ 2 * x * y * np.power(s, 2) + 2 * z * c * s, 2 * (np.power(y, 2) - 1) * np.power(s, 2) + 1, 2 * z * y * np.power(s, 2) - 2 * x * c * s ], [ 2 * x * z * np.power(s, 2) - 2 * y * c * s, 2 * z * y * np.power(s, 2) + 2 * x * c * s, 2 * (np.power(z, 2) - 1) * np.power(s, 2) + 1 ]]) for j in range(element[starting_index], element[2]): pos[j] += shift_forward for j in range(element[starting_index], element[2]): roted = np.dot(np.array(pos[j].value_in_unit(unit.angstrom)), rot) pos[j] = mm.Vec3(roted[0], roted[1], roted[2]) * unit.angstrom pos[j] -= shift_forward positions_new = pos self.positions = positions_new[:] else: raise ValueError( 'This Complex contains no positions! You CANNOT rotate!')
#Add an empty Chain to the Complex, of structure DNA cpx.add_chain('', RNA) #Add a chain to the complex using a pdb file (e.g. "xylanase.pdb") cpx.add_chain_from_PDB(PDB_PATH, parameterized=False) #Build a complex with the pdb only, to get center of mass of the pdb --# c = Complex("leaprc.ff12SB") c.add_chain_from_PDB(PDB_PATH, parameterized=False) c.build() #----------------------------------------------------------------------# #Create a sampling Cube of Diameter 50. Angstroms around the pdb center of mass cube = Space.Cube(20., centerOfMass(np.asarray(nostrom(c.positions)))) #Create a sampling Space of the direct sum of N_ELEMENTS angles rotations = Space.NAngles(N_ELEMENTS) #Initialize variables for picking out the best aptamer best_entropy = None best_sequence = None best_positions = None output.write("Initialized succesfully!\n") #for each nucleotide in GATC for ntide in 'GAUC': output.write("{0}: starting initial step for '{1}'\n".format( str(datetime.now()), ntide))
cpx.add_chain('', PROT) #Add a chain to the complex using a pdb file (e.g. "xylanase.pdb") cpx.add_chain_from_PDB(PDB_PATH, parameterized=True) #Build a complex with the pdb only, to get center of mass of the pdb --# c = Complex("leaprc.ff12SB") c.add_chain_from_PDB(PDB_PATH, parameterized=True) c.build() c.minimize() #----------------------------------------------------------------------# #Create a sampling Cube of Diameter 50. Angstroms around the pdb center of mass center = centerOfMass(np.asarray(nostrom(c.positions))) R = radius(center, np.asarray(nostrom(c.positions))) cube = Space.Cube(R - 2., center) en0 = c.get_energy()[0] #Create a sampling Space of the direct sum of N_ELEMENTS angles rotations = Space.NAngles(N_ELEMENTS) #Initialize variables for picking out the best aptamer best_entropy = None best_sequence = None best_positions = None output.write("Initialized succesfully!\n") #for each nucleotide in GATC for ntide in ['ALA', 'GLY', 'GLU', 'HIS']:
def fit_sequence_to_chain_split_join(self, chain_id, sequence): #Get the chain to be fit chain = self.chains[chain_id] #Get the current array of residues current_sequence_array = chain.sequence_array[:] #Build the new array of residues new_alias_sequence_array = sequence.split(" ") new_sequence_array = chain.structure.translate(sequence).split(' ') #Get the current positions current_positions = self.positions[:] #Get current residue starts current_residues_start = chain.residues_start[:] #Get current chain starts current_chain_start = chain.start #Build new sequence chain.create_sequence(sequence) #Rebuild the complex, excluding the chain to be fit self.rebuild(exclusion=[chain]) #Split Positions current_positions_split = [ current_positions[chain.structure. backbone_elements[residue][idx][0] + current_residues_start[idy]:chain.structure. backbone_elements[residue][idx][1] + current_residues_start[idy] + 2 - idx] for idy, residue in enumerate(current_sequence_array) for idx in [0, 1] ] positions_split = [ self.positions[chain.structure.backbone_elements[residue][0][1] + chain.residues_start[idy]:chain.structure. backbone_elements[residue][1][0] + chain.residues_start[idy]] for idy, residue in enumerate(new_sequence_array) ] positions = [] for index, residue in enumerate(chain.sequence_array): #substituent -= substituent[0] subst = positions_split[index] vec0 = subst[ chain.structure.backbone_elements[residue][0][2] - chain.structure.backbone_elements[residue][0][1]] - subst[0] vec1 = current_positions[ current_residues_start[index] + chain.structure.backbone_elements[ current_sequence_array[index]][0][2]] - current_positions[ current_residues_start[index] + chain.structure. backbone_elements[current_sequence_array[index]][0] [1]] # - current_positions_split[2*index][-2] #vec1 = current_positions[current_residues_start[index] + chain.structure.backbone[residue][0][1]][-1] - current_positions_split[2*index][-2] axis = np.cross(np.asarray(nostrom(vec0)), np.asarray(nostrom(vec1))) #print("axis: %s"%axis) if (axis == np.zeros(3)).all(): axis = np.array([1., 0., 0.]) angle = 0. else: axis /= np.linalg.norm(axis) angle = -d_ang(np.asarray(nostrom(vec0)), np.asarray(nostrom(vec1)), axis) #print("angle: %s"%angle) x, y, z = axis s = np.math.sin(angle / 2.) c = np.math.cos(angle / 2.) rot = np.array([[ 2 * (np.power(x, 2) - 1) * np.power(s, 2) + 1, 2 * x * y * np.power(s, 2) - 2 * z * c * s, 2 * x * z * np.power(s, 2) + 2 * y * c * s ], [ 2 * x * y * np.power(s, 2) + 2 * z * c * s, 2 * (np.power(y, 2) - 1) * np.power(s, 2) + 1, 2 * z * y * np.power(s, 2) - 2 * x * c * s ], [ 2 * x * z * np.power(s, 2) - 2 * y * c * s, 2 * z * y * np.power(s, 2) + 2 * x * c * s, 2 * (np.power(z, 2) - 1) * np.power(s, 2) + 1 ]]) shift_forward = subst[ chain.structure.backbone_elements[residue][0][2] - chain.structure.backbone_elements[residue][0][1]] for j in range( chain.structure.backbone_elements[residue][0][2] - chain.structure.backbone_elements[residue][0][2], len(subst)): subst[j] -= shift_forward roted = np.dot(np.array(subst[j].value_in_unit(unit.angstrom)), rot) subst[j] = mm.Vec3(roted[0], roted[1], roted[2]) * unit.angstrom subst[j] += current_positions[ current_residues_start[index] + chain.structure.backbone_elements[ current_sequence_array[index]][0][2]] #print(vec1-subst[1]+subst[0]) #substituent += current_positions_split[2*index][-1] for position in current_positions_split[2 * index][:]: positions.append(position) for position in subst[2:]: positions.append(position) for position in current_positions_split[2 * index + 1]: positions.append(position) #print("%s = %s"%(vec0, vec1)) #print("%s = %s"%(len(positions), len(self.positions))) #assert(len(positions) == len(self.positions)) for idx, position in enumerate(positions): self.positions[idx] = position
def fit_sequence_to_chain(self, chain_id, sequence): #Get the chain to be fit chain = self.chains[chain_id] #Get the current array of residues current_sequence_array = chain.sequence_array[:] #Build the new array of residues new_alias_sequence_array = sequence.split(" ") new_sequence_array = chain.structure.translate(sequence).split(' ') #Get the current positions current_positions = self.positions[:] #Get current residue starts current_residues_start = chain.residues_start[:] #Get current chain starts current_chain_start = chain.start #Get current element current_chain_element = chain.element[:] #Build new sequence chain.create_sequence(sequence) #Rebuild the complex, excluding the chain to be fit self.rebuild(exclusion=[chain]) #Translate chain to the position of the first atom to be fit self.translate_global( chain.element, current_positions[current_chain_start] - self.positions[chain.start]) vec0 = self.positions[chain.element[1]] - self.positions[ chain.element[0]] vec1 = current_positions[current_chain_element[1]] - current_positions[ current_chain_element[0]] angle = ang(nostrom(vec0), nostrom(vec1)) global_axis = mm.Vec3(*np.cross(np.asarray(nostrom( vec0)), np.asarray(nostrom(vec1)))) * unit.angstrom if (np.asarray(nostrom(global_axis)) == np.array([0., 0., 0.])).all(): global_axis = mm.Vec3(1., 0., 0.) * unit.angstrom angle = 0. #Rotate chain to fit first rotable bond ##print("chain element: %s"%chain.element) self.rotate_global(chain.element, global_axis, -angle) #Iterate over residues and their rotable elements for residue_id, [residue, residue_current] in enumerate( zip(chain.sequence_array, current_sequence_array)): for element_id, (element, element_current) in enumerate( zip(chain.structure.rotating_elements[residue], chain.structure.rotating_elements[residue_current])): ##print(element) revised0 = element[0] + chain.start + chain.residues_start[ residue_id] revised1 = element[1] + chain.start + chain.residues_start[ residue_id] revised0_current = element_current[ 0] + current_chain_start + current_residues_start[ residue_id] revised1_current = element_current[ 1] + current_chain_start + current_residues_start[ residue_id] axis = self.positions[revised1] - self.positions[revised0] if not np.linalg.norm(np.asarray(nostrom(axis))) == 0: axis /= np.linalg.norm(np.asarray(nostrom(axis))) else: axis = mm.Vec3(1., 0., 0.) #Bond to next-to-nearest neighbour along increasing indices in the element vec0 = self.positions[revised1 + 1] - self.positions[revised1] vec1 = current_positions[ revised1_current + 1] - current_positions[revised1_current] #Projection onto plane perpendicular to axis proj_vec0 = np.asarray(nostrom(vec0)) - np.dot( axis, nostrom(vec0)) * nostrom(axis) proj_vec1 = np.asarray(nostrom(vec1)) - np.dot( axis, nostrom(vec1)) * nostrom(axis) #Get angle between projections angle = d_ang(proj_vec0, proj_vec1, axis) #Rotate element by that angle, to align to backbone chain.rotate_in_residue(residue_id, element_id, -angle)
def rebuild(self, target_path="", file_name="out", exclusion=[]): old_positions = self.positions[:] self.build() #print("EXPECTED LENGTH OF POSITIONS: %s"%len(self.positions)) for index, chain in enumerate(self.chains): if not (chain in exclusion): pre_positions = self.positions[chain.start:chain.start_history] chain_positions = old_positions[chain.start:chain.start + chain.length_history] post_positions = self.positions[chain.start_history + chain. length_history:chain.start + chain.length] if len(pre_positions) != 0 and chain.prepend_history: # Fixing positions of prepended atoms from here on: pre_positions = self.positions[chain. start:chain.start_history + 1] pre_vector = self.positions[ chain.start_history + chain.structure.connect[chain.prepend_history[-1]][1] [0]] - self.positions[chain.start_history + 1] old_pre_vector = old_positions[ chain.start] - old_positions[chain.start + 1] angle = -ang(nostrom(pre_vector), nostrom(old_pre_vector)) axis = np.cross(np.asarray(nostrom(pre_vector)), np.asarray(nostrom(old_pre_vector))) if all(axis == np.zeros(3)): axis = np.array([1., 0., 0.]) angle = 0 else: axis /= np.linalg.norm(axis) x, y, z = axis phi_2 = angle / 2. pos = pre_positions[:] shift_forward = mm.Vec3(0, 0, 0) * unit.angstroms - pos[ -1 + chain.structure.connect[ chain.prepend_history[-1]][1][0]] s = np.math.sin(phi_2) c = np.math.cos(phi_2) rot = np.array( [[ 2 * (np.power(x, 2) - 1) * np.power(s, 2) + 1, 2 * x * y * np.power(s, 2) - 2 * z * c * s, 2 * x * z * np.power(s, 2) + 2 * y * c * s ], [ 2 * x * y * np.power(s, 2) + 2 * z * c * s, 2 * (np.power(y, 2) - 1) * np.power(s, 2) + 1, 2 * z * y * np.power(s, 2) - 2 * x * c * s ], [ 2 * x * z * np.power(s, 2) - 2 * y * c * s, 2 * z * y * np.power(s, 2) + 2 * x * c * s, 2 * (np.power(z, 2) - 1) * np.power(s, 2) + 1 ]]) for j in range(0, len(pos)): pos[j] += shift_forward ## LOOK HERE! # A correction for the bond length of the prepended residue / chain: # The Vector connecting the old first atom of the chain to be prepended to is multiplied by # the specified length of the connecting bond. shift_back = chain_positions[chain.structure.connect[ chain.sequence_array[len( chain.prepend_history)]][1][1]] pre_bond_shift = ( chain.structure.connect[chain.prepend_history[-1]][2] ) * old_pre_vector / np.linalg.norm( np.asarray(nostrom(old_pre_vector))) - old_pre_vector for j in range(0, len(pos)): roted = np.dot( np.array(pos[j].value_in_unit(unit.angstrom)), rot) pos[j] = mm.Vec3(roted[0], roted[1], roted[2]) * unit.angstrom pos[j] += shift_back + pre_bond_shift pre_positions = pos[:] chain_positions[0] += pre_bond_shift self.positions = self.positions[:chain. start] + pre_positions[:] + chain_positions[ 1:] + self.positions[ chain.start + chain.length:] # Stop fixing positions of prepended atoms. if len(post_positions) != 0 and chain.append_history: # Fixing positions of appended atoms from here on: post_positions = self.positions[chain.start_history + chain.length_history - 1:chain.start_history + chain.length] post_vector = self.positions[ chain.start_history + chain.length_history - 1] - self.positions[chain.start_history + chain.length_history - 2] old_post_vector = old_positions[ chain.start_history + chain.length_history - 1] - old_positions[chain.start_history + chain.length_history - 2] angle = -ang(nostrom(post_vector), nostrom(old_post_vector)) axis = np.cross(np.asarray(nostrom(post_vector)), np.asarray(nostrom(old_post_vector))) if all(axis == np.zeros(3)): axis = np.array([1., 0., 0.]) angle = 0. else: axis /= np.linalg.norm(axis) x, y, z = axis phi_2 = angle / 2. pos = post_positions[:] shift_forward = mm.Vec3(0, 0, 0) * unit.angstroms - pos[ chain.structure.connect[chain.append_history[0]][0][0]] s = np.math.sin(phi_2) c = np.math.cos(phi_2) rot = np.array( [[ 2 * (np.power(x, 2) - 1) * np.power(s, 2) + 1, 2 * x * y * np.power(s, 2) - 2 * z * c * s, 2 * x * z * np.power(s, 2) + 2 * y * c * s ], [ 2 * x * y * np.power(s, 2) + 2 * z * c * s, 2 * (np.power(y, 2) - 1) * np.power(s, 2) + 1, 2 * z * y * np.power(s, 2) - 2 * x * c * s ], [ 2 * x * z * np.power(s, 2) - 2 * y * c * s, 2 * z * y * np.power(s, 2) + 2 * x * c * s, 2 * (np.power(z, 2) - 1) * np.power(s, 2) + 1 ]]) for j in range(0, len(pos)): pos[j] += shift_forward ## LOOK HERE! # A correction for the bond length of the prepended residue / chain: # The Vector connecting the old first atom of the chain to be prepended to is multiplied by # the specified length of the connecting bond. post_bond_shift = ( chain.structure.connect[chain.append_history[0]][2] ) * old_post_vector / np.linalg.norm( np.asarray(nostrom(old_post_vector))) - old_post_vector shift_back = chain_positions[chain.structure.connect[ chain.sequence_array[-len(chain.append_history)]][0] [1]] for pos_idx, pos_elem in enumerate(pos): roted = np.dot( np.array(pos_elem.value_in_unit(unit.angstrom)), rot) pos[pos_idx] = mm.Vec3(roted[0], roted[1], roted[2]) * unit.angstrom pos[pos_idx] += shift_back + post_bond_shift post_positions = pos[:] chain_positions[-1] += post_bond_shift #print("ACTUAL_LENGTH: %s"%(len(chain_positions[:-1] + post_positions[:]))) #print(len(self.positions[chain.start:chain.start+chain.length])) self.positions = self.positions[:chain. start] + chain_positions[:-1] + post_positions[:] + self.positions[ chain.start + chain.length:] # Stop fixing positions of propended atoms. if not (chain.append_history or chain.prepend_history): self.positions = self.positions[:chain.start] + old_positions[ chain.start_history:chain.start_history + chain.length_history] + self.positions[chain.start + chain.length:] #print("LENGHT OF POSITIONS: %s"%len(self.positions)) #pass else: pass