def generateAA(aaName): geo = Geometry.geometry(aaName) geo.phi = 0 geo.psi_im1 = 0 structure = PeptideBuilder.initialize_res(geo) tx = -np.pi / 2.0 Rx = np.array([[1, 0, 0], [0, cos(tx), -sin(tx)], [0, sin(tx), cos(tx)]]) for atom in structure.get_atoms(): atom.transform(Rx, np.array([0, 0, 0])) nAtom = list(structure.get_atoms())[0] nV = nAtom.get_coord() I = np.identity(3) for atom in structure.get_atoms(): atom.transform(I, -nV) R = rotaxis(np.pi, list(structure.get_atoms())[1].get_vector()) for atom in structure.get_atoms(): atom.transform(R, np.array([0, 0, 0])) # print(list(structure.get_atoms())[1].get_coord(), list(structure.get_atoms())[1]) out = Bio.PDB.PDBIO() out.set_structure(structure) out.save("example.pdb") return structure[0]['A'][1]
def test_Vector_angles(self): """Test Vector angles.""" angle = random() * numpy.pi axis = Vector(random(3) - random(3)) axis.normalize() m = rotaxis(angle, axis) cangle, caxis = m2rotaxis(m) self.assertAlmostEqual(angle, cangle, places=3) self.assertTrue( numpy.allclose(list(map(int, (axis - caxis).get_array())), [0, 0, 0]), "Want %r and %r to be almost equal" % (axis.get_array(), caxis.get_array()))
def transform(structure): tx = -np.pi / 2.0 Rx = np.array([[1, 0, 0], [0, cos(tx), -sin(tx)], [0, sin(tx), cos(tx)]]) for atom in structure.get_atoms(): atom.transform(Rx, np.array([0, 0, 0])) nAtom = list(structure.get_atoms())[0] nV = nAtom.get_coord() I = np.identity(3) for atom in structure.get_atoms(): atom.transform(I, -nV) R = rotaxis(np.pi, list(structure.get_atoms())[1].get_vector()) for atom in structure.get_atoms(): atom.transform(R, np.array([0, 0, 0])) return structure
def randomize_starting_position(ligand_file, complex_file, outputfolder=".", nposes=200, test=False, user_center=None, logger=None): """ Randomize initial ligand position around the receptor. Default number of poses = 200. :param ligand_file: :param complex_file: :param nposes: :return: """ if test: np.random.seed(42) # read in files parser = PDBParser() output = [] structure = parser.get_structure('protein', complex_file) ligand = parser.get_structure('ligand', ligand_file) COI = np.zeros(3) # get center of interface (if PPI) if user_center: try: chain_id, res_number, atom_name = user_center.split(":") except ValueError: raise cs.WrongAtomStringFormat(f"The specified atom is wrong '{user_center}'. \ Should be 'chain:resnumber:atomname'") for chain in structure.get_chains(): if chain.id == chain_id: for residue in chain.get_residues(): if residue.id[1] == int(res_number): for atom in residue.get_atoms(): if atom.name == atom_name: COI = np.array(list(atom.get_vector())) # calculate protein and ligand COM com_protein = calculate_com(structure) com_ligand = calculate_com(ligand) # calculating the maximum d of the ligand coor_ligand = [] for atom in ligand.get_atoms(): coor_ligand.append(list(atom.get_vector() - com_ligand)) coor_ligand = np.array(coor_ligand) coor_ligand_max = np.amax(coor_ligand, axis=0) d_ligand = np.sqrt(np.sum(coor_ligand_max ** 2)) # set threshold for near and far contacts based on ligand d if d_ligand / 2 < 5.0: d5_ligand = 5.0 else: d5_ligand = d_ligand / 2 + 1 if d_ligand > 8.0: d8_ligand = d_ligand / 2 + 4 else: d8_ligand = 8.0 # calculate vector to move the ligandi if user_center: move_vector = com_ligand - COI else: move_vector = com_ligand - com_protein # translate the ligand to the protein COM (COI for PPI) original_coords = [] for atom in ligand.get_atoms(): ligand_origin = np.array(list(atom.get_vector())) - move_vector original_coords.append(ligand_origin) atom.set_coord(ligand_origin) # calculating the maximum radius of the protein from the origin coor = [] for atom in structure.get_atoms(): coor.append(list(atom.get_vector() - com_protein)) coor = np.array(coor) coor_max = np.amax(coor, axis=0) d = np.sqrt(np.sum(coor_max ** 2)) # radius of the sphere from the origin D = 10.0 if user_center else np.ceil(6.0 + d) D_initial = D logger.info("Sampling {}A spherical box around the centre of the receptor/interface.".format(D)) if user_center: sphere_cent = COI else: sphere_cent = com_protein j = 0 logger.info("Generating {} poses...".format(nposes)) start_time = time.time() while (j < nposes): # generate random coordinates phi = np.random.uniform(0, 2 * np.pi) costheta = np.random.uniform(-1, 1) u = np.random.uniform(0, 1) theta = np.arccos(costheta) r = D * np.cbrt(u) x = r * np.sin(theta) * np.cos(phi) y = r * np.sin(theta) * np.sin(phi) z = r * np.cos(theta) # move ligand to the starting point (protein COM) for atom, coord in zip(ligand.get_atoms(), original_coords): atom.set_coord(coord) # translate ligand to a random position translation = (x, y, z) for atom in ligand.get_atoms(): new_pos_lig_trans = np.array(list(atom.get_vector())) - translation atom.set_coord(new_pos_lig_trans) # calculate ligand COM in the new position new_ligand_COM = calculate_com(ligand) # rotate ligand vector = Vector(new_ligand_COM) rotation_matrix = rotaxis(np.random.randint(0, 2 * np.pi), vector) for atom in ligand.get_atoms(): coords_after = atom.get_vector().left_multiply(rotation_matrix) atom.set_coord(coords_after) # check if it's inside the sampling sphere dist = np.sqrt((new_ligand_COM[0] - sphere_cent[0]) ** 2 + (new_ligand_COM[1] - sphere_cent[1]) ** 2 + ( new_ligand_COM[2] - sphere_cent[2]) ** 2) if dist < D: # check contacts at: 5A (no contacts) and 8A (needs contacts) protein_list = Selection.unfold_entities(structure, "A") contacts5 = [] contacts8 = [] ligand_atoms = list(ligand.get_atoms()) contacts5.append( NeighborSearch(protein_list).search(new_ligand_COM, d5_ligand, "S")) contacts8 = NeighborSearch(protein_list).search(new_ligand_COM, d8_ligand, "S") if contacts8 and not any(contacts5): j += 1 io = PDBIO() io.set_structure(ligand) output_name = os.path.join(outputfolder, 'ligand{}.pdb'.format(j)) io.save(output_name) output.append(output_name) start_time = time.time() end_time = time.time() total_time = end_time - start_time if total_time > 60: D += 1 if D - D_initial >= 20: logger.info("Original box increased by 20A. Aborting...") break start_time = end_time logger.info("Increasing sampling box by 1A.") logger.info("{} poses created successfully.".format(j)) return output, D, list(sphere_cent)
def randomize_starting_position(parameters, box_center=None, box_radius=None): """ Randomize initial ligand position around the receptor. Parameters ---------- parameters : Parameters Parameters object passed from Adaptive.simulation. box_center : Union[List[float], str] Box center defined by the user, either using a list of coordinates or by specifying an atom, e.g. A:123:CA box_radius : float Box radius defined by the user. Returns ------- A list of PDB files with random ligand positions. """ np.random.seed(parameters.seed) # When running SiteFinder, the users can narrow down the area where inputs will be # spawned by setting box radius and center. We're setting box_center as COI to avoid crazy code changes until 2.0. if parameters.site_finder: parameters.center_of_interface = box_center if box_center else None # Retrieve atom information from the string (if PPI or SF) if parameters.center_of_interface: pattern = r"([A-z]\:\d{1,4}\:[A-Z0-9]{1,4})" match = re.match(pattern, parameters.center_of_interface) if not match: raise cs.WrongAtomStringFormat(f"The specified atom is wrong '{parameters.center_of_interface}'. " f"Should be 'chain:residue number:atom name'.") else: chain_id, res_number, atom_name = parameters.center_of_interface.split(":") # Load PDB files into biopython parser = PDBParser() structure = parser.get_structure('protein', parameters.receptor) ligand = parser.get_structure('ligand', parameters.ligand_ref) output = [] COI = np.zeros(3) # initializing to [0, 0, 0] # Get center of interface (if PPI or custom SF box) if parameters.center_of_interface: for chain in structure.get_chains(): if chain.id == chain_id: for residue in chain.get_residues(): if residue.id[1] == int(res_number): for atom in residue.get_atoms(): if atom.name == atom_name: COI = np.array(list(atom.get_vector())) print("Center of interface:", COI) # calculate protein and ligand COM com_protein = calculate_com(structure) com_ligand = calculate_com(ligand) # calculating the maximum dimensions of the ligand coor_ligand = [] for atom in ligand.get_atoms(): coor_ligand.append(list(atom.get_vector() - com_ligand)) coor_ligand = np.array(coor_ligand) coor_ligand_max = np.amax(coor_ligand, axis=0) d_ligand = np.sqrt(np.sum(coor_ligand_max ** 2)) # set threshold for near and far contacts based on ligand dimensions if d_ligand / 2 < 5.0: d5_ligand = 5.0 else: d5_ligand = d_ligand / 2 + 1 if d_ligand > 8.0: d8_ligand = d_ligand / 2 + 4 else: d8_ligand = 8.0 # calculate vector to move the ligand respectively to the center of interface of center of mass of the protein if parameters.center_of_interface: move_vector = com_ligand - COI else: move_vector = com_ligand - com_protein # translate the ligand to the protein COM (COI for PPI) original_coords = [] for atom in ligand.get_atoms(): ligand_origin = np.array(list(atom.get_vector())) - move_vector original_coords.append(ligand_origin) atom.set_coord(ligand_origin) # calculating the maximum radius of the protein from the origin coor = [] for atom in structure.get_atoms(): coor.append(list(atom.get_vector() - com_protein)) coor = np.array(coor) coor_max = np.amax(coor, axis=0) d = np.sqrt(np.sum(coor_max ** 2)) # Calculate radius of the sphere from the origin if parameters.center_of_interface: if parameters.site_finder and box_radius: D = box_radius elif box_radius: # GPCR and OutIn D = box_radius else: # ppi D = 10 else: D = np.ceil(6.0 + d) D_initial = D parameters.logger.info("Sampling {}A spherical box around the centre of the receptor/interface.".format(D)) if parameters.center_of_interface: sphere_cent = COI else: sphere_cent = com_protein j = 0 parameters.logger.info("Generating {} poses...".format(parameters.poses)) start_time = time.time() while j < parameters.poses: # generate random coordinates phi = np.random.uniform(0, 2 * np.pi) costheta = np.random.uniform(-1, 1) u = np.random.uniform(0, 1) theta = np.arccos(costheta) r = D * np.cbrt(u) x = r * np.sin(theta) * np.cos(phi) y = r * np.sin(theta) * np.sin(phi) z = r * np.cos(theta) # move ligand to the starting point (protein COM) for atom, coord in zip(ligand.get_atoms(), original_coords): atom.set_coord(coord) # translate ligand to a random position translation = (x, y, z) for atom in ligand.get_atoms(): new_pos_lig_trans = np.array(list(atom.get_vector())) - translation atom.set_coord(new_pos_lig_trans) # calculate ligand COM in the new position new_ligand_COM = calculate_com(ligand) # rotate ligand vector = Vector(new_ligand_COM) rotation_matrix = rotaxis(np.random.randint(0, 2 * np.pi), vector) for atom in ligand.get_atoms(): coords_after = atom.get_vector().left_multiply(rotation_matrix) atom.set_coord(coords_after) # check if it's inside the sampling sphere dist = np.sqrt((new_ligand_COM[0] - sphere_cent[0]) ** 2 + (new_ligand_COM[1] - sphere_cent[1]) ** 2 + ( new_ligand_COM[2] - sphere_cent[2]) ** 2) if dist < D: # check contacts at: 5A (no contacts) and 8A (needs contacts) protein_list = Selection.unfold_entities(structure, "A") contacts5 = NeighborSearch(protein_list).search(new_ligand_COM, d5_ligand, "S") contacts8 = NeighborSearch(protein_list).search(new_ligand_COM, d8_ligand, "S") if contacts8 and not any(contacts5): j += 1 io = PDBIO() io.set_structure(ligand) output_name = os.path.join(parameters.inputs_dir, 'ligand{}.pdb'.format(j)) io.save(output_name) output.append(output_name) start_time = time.time() end_time = time.time() total_time = end_time - start_time if total_time > 60: D += 1 if D - D_initial >= 20: parameters.logger.info("Original box increased by 20A. Aborting...") break start_time = end_time parameters.logger.info("Increasing sampling box by 1A.") parameters.logger.info("{} poses created successfully.".format(j)) return output, D, list(sphere_cent)