def test_rotmat_0(self): """Test rotmat when the rotation is 0 deg (singularity).""" v1 = Vector([1.0, 0.8, 0]) v2 = Vector([1.0, 0.8, 0]) rot = rotmat(v1, v2) v3 = v1.left_multiply(rot) self.assertTrue(numpy.allclose(v1.get_array(), v3.get_array()))
def rotateTranslatePdb(fname, rotX, rotY, rotZ, transX, transY, transZ, fnameOut=None): print(fname, rotX, rotY, rotZ, transX, transY, transZ, fnameOut) struct = myPDBParser(QUIET=True).get_structure(fname) rotationX = rotaxis(-rotX, Vector(1, 0, 0)) rotationY = rotaxis(rotY, Vector(0, 1, 0)) rotationZ = rotaxis(-rotZ, Vector(0, 0, 1)) translation = np.array((transX, transY, transZ), 'f') rotation = rotationX.dot(rotationY).dot(rotationZ) struct.transform(rotation, translation) if fnameOut is not None: fnameOut = fnameOut pdbWriter = PDBIO() pdbWriter.set_structure(struct) pdbWriter.save(fnameOut) return struct
def test_m2rotaxis_90(self): """Test 90 deg rotation.""" v1 = Vector(0, 0, 1) v2 = Vector(0, 1, 0) rot = rotmat(v1, v2) angle, axis = m2rotaxis(rot) self.assertTrue(numpy.allclose(axis.get_array(), [-1.0, 0.0, 0.0])) self.assertTrue(abs(angle - numpy.pi / 2) < 1e-5)
def test_m2rotaxis_0(self): """Test 0 deg rotation. Axis must be [1, 0, 0] as per Vector documentation.""" v1 = Vector([1.0, 0.8, 0]) v2 = Vector([1.0, 0.8, 0]) rot = rotmat(v1, v2) angle, axis = m2rotaxis(rot) self.assertTrue(numpy.allclose(axis.get_array(), [1, 0, 0])) self.assertTrue(abs(angle) < 1e-5)
def test_m2rotaxis_180(self): """Test 180 deg rotation.""" v1 = Vector([1.0, 0.8, 0]) v2 = Vector([-1.0, -0.8, 0]) rot = rotmat(v1, v2) angle, axis = m2rotaxis(rot) self.assertTrue(abs(axis * v1) < 1e-5) # axis orthogonal to v1 self.assertTrue(abs(angle - numpy.pi) < 1e-5)
def test_refmat(self): v1 = Vector(0, 0, 1) v2 = Vector(0, 1, 0) ref = refmat(v1, v2) self.assertTrue(numpy.allclose(ref[0], [1.0, 0.0, 0.0])) self.assertTrue(numpy.allclose(ref[1], [0.0, 0.0, 1.0])) self.assertTrue(numpy.allclose(ref[2], [0.0, 1.0, 0.0])) self.assertTrue( numpy.allclose(v1.left_multiply(ref).get_array(), [0.0, 1.0, 0.0]))
def test_refmat(self): """Test refmat can mirror one matrix to another.""" v1 = Vector(0, 0, 1) v2 = Vector(0, 1, 0) ref = refmat(v1, v2) self.assertTrue(numpy.allclose(ref[0], [1.0, 0.0, 0.0])) self.assertTrue(numpy.allclose(ref[1], [0.0, 0.0, 1.0])) self.assertTrue(numpy.allclose(ref[2], [0.0, 1.0, 0.0])) self.assertTrue( numpy.allclose(v1.left_multiply(ref).get_array(), [0.0, 1.0, 0.0]))
def __init__(self, donor, hydrogen, acceptor, acc_support): """Takes four sets of coord vectors.""" self.donor = Vector(donor) self.acceptor = Vector(acceptor) self.hydrogen = Vector(hydrogen) self.acc_support = Vector(acc_support) # helper vectors self.dh = self.hydrogen - self.donor self.ha = self.hydrogen - self.acceptor self.acs = self.acc_support - self.acceptor
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 test_rotmat_90(self): """Test regular 90 deg rotation.""" v1 = Vector(0, 0, 1) v2 = Vector(0, 1, 0) rot = rotmat(v1, v2) self.assertTrue(numpy.allclose(rot[0], numpy.array([1.0, 0.0, 0.0]))) self.assertTrue(numpy.allclose(rot[1], numpy.array([0.0, 0.0, 1.0]))) self.assertTrue(numpy.allclose(rot[2], numpy.array([0.0, -1.0, 0.0]))) self.assertTrue( numpy.allclose(v1.left_multiply(rot).get_array(), [0.0, 1.0, 0.0])) self.assertTrue( numpy.allclose( v1.right_multiply(numpy.transpose(rot)).get_array(), [0.0, 1.0, 0.0]))
def get_endpoints_from_modules(modules): """ Get the averaged endpoints of the modules as a list of vectors """ # starting point endpoints = [Vector(*modules[0][0])] for i in range(len(modules) - 1): # calculate the midpoint of start/end of interior modules midpoint = Vector(*((modules[i][-1] + modules[i + 1][0]) / 2)) endpoints.append(midpoint) # ending point endpoints.append(Vector(*modules[-1][-1])) return endpoints
def calculate_dihedral_angels(original_aa_sequence, atomic_coords): aa_list = protein_id_to_str(original_aa_sequence) assert int(atomic_coords.shape[1]) == 9 atomic_coords = list( [Vector(v) for v in atomic_coords.contiguous().view(-1, 3).numpy()]) phi_list = [0] psi_list = [] omega_list = [] for i, coord in enumerate(atomic_coords): if int(original_aa_sequence[int(i / 3)]) == 0: print("ERROR: Reached end of protein, stopping") break if i % 3 == 0: if i != 0: phi_list.append( Bio.PDB.calc_dihedral(atomic_coords[i - 1], atomic_coords[i], atomic_coords[i + 1], atomic_coords[i + 2])) if i + 3 < len(atomic_coords): psi_list.append( Bio.PDB.calc_dihedral(atomic_coords[i], atomic_coords[i + 1], atomic_coords[i + 2], atomic_coords[i + 3])) omega_list.append( Bio.PDB.calc_dihedral(atomic_coords[i + 1], atomic_coords[i + 2], atomic_coords[i + 3], atomic_coords[i + 4])) psi_list.append(0) omega_list.append(0) return (aa_list, phi_list, psi_list, omega_list)
def make_vectors(row, points): """ Turn 3D point information into BioPython Vector objects """ vectors = [] for i in [3*j for j in points]: vectors.append(Vector(*coords[row,i:i+3])) return vectors
def get_vector(self): """Return coordinates as Vector. :return: coordinates as 3D vector :rtype: Bio.PDB.Vector class """ x, y, z = self.coord return Vector(x, y, z)
def test_Vector(self): """Test Vector object.""" v1 = Vector(0, 0, 1) v2 = Vector(0, 0, 0) v3 = Vector(0, 1, 0) v4 = Vector(1, 1, 0) self.assertEqual(calc_angle(v1, v2, v3), 1.5707963267948966) self.assertEqual(calc_dihedral(v1, v2, v3, v4), 1.5707963267948966) self.assertTrue( numpy.array_equal((v1 - v2).get_array(), numpy.array([0.0, 0.0, 1.0]))) self.assertTrue( numpy.array_equal((v1 - 1).get_array(), numpy.array([-1.0, -1.0, 0.0]))) self.assertTrue( numpy.array_equal((v1 - (1, 2, 3)).get_array(), numpy.array([-1.0, -2.0, -2.0]))) self.assertTrue( numpy.array_equal((v1 + v2).get_array(), numpy.array([0.0, 0.0, 1.0]))) self.assertTrue( numpy.array_equal((v1 + 3).get_array(), numpy.array([3.0, 3.0, 4.0]))) self.assertTrue( numpy.array_equal((v1 + (1, 2, 3)).get_array(), numpy.array([1.0, 2.0, 4.0]))) self.assertTrue( numpy.array_equal(v1.get_array() / 2, numpy.array([0, 0, 0.5]))) self.assertTrue( numpy.array_equal(v1.get_array() / 2, numpy.array([0, 0, 0.5]))) self.assertEqual(v1 * v2, 0.0) self.assertTrue( numpy.array_equal((v1**v2).get_array(), numpy.array([0.0, -0.0, 0.0]))) self.assertTrue( numpy.array_equal((v1**2).get_array(), numpy.array([0.0, 0.0, 2.0]))) self.assertTrue( numpy.array_equal((v1**(1, 2, 3)).get_array(), numpy.array([0.0, 0.0, 3.0]))) self.assertEqual(v1.norm(), 1.0) self.assertEqual(v1.normsq(), 1.0) v1[2] = 10 self.assertEqual(v1.__getitem__(2), 10)
def get_centroid_vector(module): """ Get the centroid of a module (a numpy matrix of coordinates) as a vector eg. x = get_CA_coords(1,1) v = get_centroid_vector(x[0]) """ x = np.mean(module[:, 0]) y = np.mean(module[:, 1]) z = np.mean(module[:, 2]) return Vector(x, y, z)
def get_centroids_and_endpoints_from_modules(modules): """ Get the averaged endpoints and centroids of each module as a list of vectors """ centroids = [] # calculate centroids for each module for module in modules: centroids.append(np.mean(module, axis=0)) points_first = modules[0][0] #very first point of the protein points_last = modules[4][-1] #very last points of the protein midpoints = [] for i in range(0, 4): # calculate midpoint between start and end of neighbouring modules midpoint = (modules[i][-1] + modules[i + 1][0]) / 2 # add midpoints to a list midpoints.append(midpoint) points = points_first #begin assembling vector with first point of protein points = np.append(points, centroids[0]) #add first centroid centroids_four = centroids[ 1:] #remove the first centroid from the list of other centroids # add the rest of the centroids and midpoints for i in range(0, 4): # here, we add the midpoint twice so that list contains groups of three points = np.append(points, midpoints[i]) points = np.append(points, centroids_four[i]) points = np.append(points, points_last) #finish protein with last point # turn list of points into a list of lists, one list for each module representation i = 0 group_points = [] while i < len(points): group_points.append(points[i:i + 3]) i = i + 3 # isolate x,y,z coordinates group_points = np.array(group_points) x2 = group_points[:, 0] y2 = group_points[:, 1] z2 = group_points[:, 2] """Vectorising the points """ vs = [] for x, y, z in zip(x2, y2, z2): v = Vector(x, y, z) vs.append(v) return x2, y2, z2, vs
def build_coord(vec1, vec2, vec3, dist, angle, torsion, matrix=None): """" Builds coordinates assuming a reference frame: A (-1/-1/0) B (-1/0/0) C (0/0/0) """ angle = math.radians(180 - angle) torsion = math.radians(torsion) # create initial vector vec_x = dist * math.cos(angle) vec_y = dist * math.cos(torsion) * math.sin(angle) vec_z = dist * math.sin(torsion) * math.sin(angle) # TODO: cache matrices for (dist/angle/torsion) (memoize pattern?) vec_d2 = Vector([vec_x, vec_y, vec_z]) if matrix == None: matrix = get_ref_matrix(vec1, vec2, vec3) result_vec = vec_d2.right_multiply(matrix) + vec3 return result_vec
def test_normalization(self): """Test Vector normalization.""" v1 = Vector([2, 0, 0]) self.assertTrue( numpy.array_equal(v1.normalized().get_array(), numpy.array([1, 0, 0])) ) # State of v1 should not be affected by `normalized` self.assertTrue(numpy.array_equal(v1.get_array(), numpy.array([2, 0, 0]))) v1.normalize() # State of v1 should be affected by `normalize` self.assertTrue(numpy.array_equal(v1.get_array(), numpy.array([1, 0, 0])))
def build_coords_2xSP3(dst, at0, at1, at2): """ Generates coordinates for two SP3 bonds given the other two **dst** Bond distance **at0** Central atom **at1** atom with existing bond **at2** atom with existing bond """ cr0 = Vector(at0.get_coord()) cr1 = Vector(at1.get_coord()) cr2 = Vector(at2.get_coord()) axe = cr0 - cr1 mat = rotaxis(120. * pi / 180., axe) bond = cr2 - cr0 bond.normalize() bond._ar = bond._ar * dst cr3 = cr0 + bond.left_multiply(mat) cr4 = cr0 + bond.left_multiply(mat).left_multiply(mat) crs = [] crs.append(cr3._ar) crs.append(cr4._ar) return crs
def write_to_pdb_strcture(atomic_coords, aaSequence, prot_id): _aa_dict_inverse = {v: k for k, v in AA_ID_DICT.items()} atomic_coords = list([Vector(v) for v in atomic_coords.numpy()]) aa_list = [] phi_list = [] psi_list = [] omega_list = [] for i, coord in enumerate(atomic_coords): if int(aaSequence[int(i / 3)]) == 0: print("Reached end of protein, stopping") break if i % 3 == 0: aa_symbol = _aa_dict_inverse[int(aaSequence[int(i / 3)])] aa_list.append(aa_symbol) if i != 0: phi_list.append( math.degrees( Bio.PDB.calc_dihedral(atomic_coords[i - 1], atomic_coords[i], atomic_coords[i + 1], atomic_coords[i + 2]))) if i + 3 < len(atomic_coords) and int( aaSequence[int(i / 3) + 1]) != 0: psi_list.append( math.degrees( Bio.PDB.calc_dihedral(atomic_coords[i], atomic_coords[i + 1], atomic_coords[i + 2], atomic_coords[i + 3]))) omega_list.append( math.degrees( Bio.PDB.calc_dihedral(atomic_coords[i + 1], atomic_coords[i + 2], atomic_coords[i + 3], atomic_coords[i + 4]))) out = Bio.PDB.PDBIO() structure = PeptideBuilder.make_structure(aa_list, phi_list, psi_list, omega_list) out.set_structure(structure) out.save("output/protein_" + str(prot_id) + ".pdb")
def protein_synthesis(l,t,d,t5,t95,d5,d95): """ protein_synthesis takes all the lengths, angles and dihedrals and returns points in 3-D space using rotation matrices, as well as returning the points in space of the 5th and 95th percentiles of the angles and dihedrals """ V=[] VA5=[] VA95=[] VD5=[] VD95=[] #rotation matrices for the second vector, rotating about a vector perpendicular to the first vector if (t[0] >= 0): RT = rotaxis(math.pi - t[0], Vector(0, 1, 0)) elif (t[0] < 0): RT = rotaxis(-(math.pi - t[0]), Vector(0, 1, 0)) if (t5[0] >= 0): RT5 = rotaxis(math.pi - t5[0], Vector(0, 1, 0)) elif (t[0] < 0): RT5 = rotaxis(-(math.pi - t5[0]), Vector(0, 1, 0)) if (t5[0] >= 0): RT95 = rotaxis(math.pi - t95[0], Vector(0, 1, 0)) elif (t[0] < 0): RT95 = rotaxis(-(math.pi - t95[0]), Vector(0, 1, 0)) #First 3 points for the representation #point 0 V.append(Vector(0,0,0)) #point 1 V.append(Vector(l[0],0,0)) #point 2, found by rotating the original vector and changing the length V.append(V[1]+(V[1].left_multiply(RT)).normalized()**l[1]) #Points for the 5th and 95th percentiles # point 0 VA5.append(Vector(0, 0, 0)) # point 1 VA5.append(Vector(l[0], 0, 0)) # point 2 VA5.append(V[1] + (V[1].left_multiply(RT5)).normalized() ** l[1]) # point 0 VA95.append(Vector(0, 0, 0)) # point 1 VA95.append(Vector(l[0], 0, 0)) # point 2 VA95.append(V[1] + (V[1].left_multiply(RT95)).normalized() ** l[1]) # point 0 VD5.append(Vector(0, 0, 0)) # point 1 VD5.append(Vector(l[0], 0, 0)) # point 2 VD5.append(V[1] + (V[1].left_multiply(RT)).normalized() ** l[1]) # point 0 VD95.append(Vector(0, 0, 0)) # point 1 VD95.append(Vector(l[0], 0, 0)) # point 2 VD95.append(V[1] + (V[1].left_multiply(RT)).normalized() ** l[1]) #loops through all the lengths, angles and dihedrals, creating new vectors and points in 3-D space i=2 while (i<=len(l)-1): #New angle rotation matrices if (t[i-1] >= 0): RT = rotaxis(math.pi - t[i-1], (V[i] - V[i-1]) ** (V[i-1]-V[i-2])) elif (t[i-1] < 0): RT = rotaxis(-(math.pi - t[i-1]), (V[i] - V[i-1]) ** (V[i-1]-V[i-2])) if (t5[i-1] >= 0): RT5 = rotaxis(math.pi - t5[i-1], (V[i] - V[i-1]) ** (V[i-1]-V[i-2])) elif (t5[i-1] < 0): RT5 = rotaxis(-(math.pi - t5[i-1]), (V[i] - V[i-1]) ** (V[i-1]-V[i-2])) if (t95[i-1] >= 0): RT95 = rotaxis(math.pi - t95[i-1], (V[i] - V[i-1]) ** (V[i-1]-V[i-2])) elif (t95[i-1] < 0): RT95 = rotaxis(-(math.pi - t95[i-1]), (V[i] - V[i-1]) ** (V[i-1]-V[i-2])) #New dihedral rotation matrices if (d[i-2] >= 0): RD = rotaxis((math.pi - d[i-2]), V[i] - V[i-1]) elif (d[i-2] < 0): RD = rotaxis(-(math.pi - d[i-2]), V[i] - V[i-1]) if (d5[i-2] >= 0): RD5 = rotaxis((math.pi - d5[i-2]), V[i] - V[i-1]) elif (d5[i-2] < 0): RD5 = rotaxis(-(math.pi - d5[i-2]), V[i] - V[i-1]) if (d95[i-2] >= 0): RD95 = rotaxis((math.pi - d95[i-2]), V[i] - V[i-1]) elif (d95[i-2] < 0): RD95 = rotaxis(-(math.pi - d95[i-2]), V[i] - V[i-1]) #point i+1 #rotates by angles and by dihedral V.append(V[i]+(((V[i]-V[i-1]).left_multiply(RT)).left_multiply(RD)).normalized()**l[i]) VA5.append(V[i] + (((V[i] - V[i - 1]).left_multiply(RT5)).left_multiply(RD)).normalized() ** l[i]) VA95.append(V[i] + (((V[i] - V[i - 1]).left_multiply(RT95)).left_multiply(RD)).normalized() ** l[i]) VD5.append(V[i] + (((V[i] - V[i - 1]).left_multiply(RT)).left_multiply(RD5)).normalized() ** l[i]) VD95.append(V[i] + (((V[i] - V[i - 1]).left_multiply(RT)).left_multiply(RD95)).normalized() ** l[i]) i=i+1 return V,VA5,VA95,VD5,VD95
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 pixelate_atoms_in_box(site, model, pixels, index): """ pixelate atoms in residue-centered box by BINWIDTH """ residues = list(model.get_residues()) ori = Vector(0, 0, 0) vec_x = Vector(0, 0, 0) vec_y = Vector(0, 0, 0) vec_z = Vector(0, 0, 0) int_coord_x = [0, 0] int_coord_y = [0, 0] int_coord_z = [0, 0] prob_x = [0, 0] prob_y = [0, 0] prob_z = [0, 0] # print(type(site)) res_index1 = index if str(type(site)) in '<class \'Bio.PDB.Residue.Residue\'>': local_ref = [ori, vec_x, vec_y, vec_z] calc_local_reference(site, local_ref) else: local_ref = [ori, vec_x, vec_y, vec_z] calc_neg_local_reference(site, local_ref) count_C = 0 count_O = 0 count_N = 0 count_P = 0 res_index2 = 0 for residue2 in residues: if residue2.resname in DICT_RES_NAME: residue2.resname = DICT_RES_NAME[residue2.resname] if residue2.resname in {' A', ' U', ' G', ' C'}: if not is_neighbor_residue(local_ref, residue2): res_index2 += 1 continue res_name = residue2.get_resname()[2] for atom in residue2: atom_name = atom.get_name() vector = atom.get_vector() if atom_name not in ATOMS_NAME: continue local_coordinate = Vector(0, 0, 0) if not is_neighbor_atom(local_ref, atom, local_coordinate): continue lattice_3d_point(local_coordinate, int_coord_x, int_coord_y, int_coord_z, prob_x, prob_y, prob_z) if atom_name in DICT_CHARGE: atom_charge = DICT_CHARGE[atom_name] elif atom_name == 'O5\'': if is_head_residue(residues, res_index2, residue2): atom_charge = DICT_CHARGE_O5S['head'] else: atom_charge = DICT_CHARGE_O5S['nonhead'] elif atom_name == 'O3\'': if is_tail_residue(residues, res_index2, residue2): atom_charge = DICT_CHARGE_O3S['tail'] else: atom_charge = DICT_CHARGE_O3S['nontail'] elif atom_name == 'C1\'': atom_charge = DICT_CHARGE_C1S[res_name] elif atom_name == 'N9': atom_charge = DICT_CHARGE_N9[res_name] elif atom_name == 'C8': atom_charge = DICT_CHARGE_C8[res_name] elif atom_name == 'N7': atom_charge = DICT_CHARGE_N7[res_name] elif atom_name == 'C5': atom_charge = DICT_CHARGE_C5[res_name] elif atom_name == 'C6': atom_charge = DICT_CHARGE_C6[res_name] elif atom_name == 'N1': atom_charge = DICT_CHARGE_N1[res_name] elif atom_name == 'C2': atom_charge = DICT_CHARGE_C2[res_name] elif atom_name == 'N3': atom_charge = DICT_CHARGE_N3[res_name] elif atom_name == 'C4': atom_charge = DICT_CHARGE_C4[res_name] elif atom_name == 'O2': atom_charge = DICT_CHARGE_O2[res_name] else: continue for i in range(1): if int_coord_x[i] < 0 or int_coord_x[i] >= NBINS: continue for j in range(1): if int_coord_y[j] < 0 or int_coord_y[j] >= NBINS: continue for k in range(1): if int_coord_z[k] < 0 or int_coord_z[k] >= NBINS: continue atom_name = dict_atom_name(atom_name) if atom_name == 'C': pixels[res_index1][0][int_coord_x[i]][ int_coord_y[j]][int_coord_z[k]] += 1 count_C += 1 elif atom_name == 'O': pixels[res_index1][1][int_coord_x[i]][ int_coord_y[j]][int_coord_z[k]] += 1 count_O += 1 elif atom_name == 'N': pixels[res_index1][2][int_coord_x[i]][ int_coord_y[j]][int_coord_z[k]] += 1 count_N += 1 elif atom_name == 'P': pixels[res_index1][3][int_coord_x[i]][ int_coord_y[j]][int_coord_z[k]] += 1 count_P += 1 pixels[res_index1][4][int_coord_x[i]][ int_coord_y[j]][int_coord_z[k]] += atom_charge """if res_index1 == 0 and int_coord_x[i] == 23 and int_coord_y[j] == 6 and int_coord_z[k] == 3: print (atom_name, atom_mass, atom_charge, prob_x[i], prob_y[j], prob_z[k], residue2.get_full_id()) """ res_index2 += 1 # print(count_C, ' ', count_O, " ", count_N, ' ', count_P) return pixels
def calculateCoordinates(refA: Residue, refB: Residue, refC: Residue, L: float, ang: float, di: float) -> np.ndarray: AV = refA.get_vector() BV = refB.get_vector() CV = refC.get_vector() CA = AV - CV CB = BV - CV ##CA vector AX = CA[0] AY = CA[1] AZ = CA[2] ##CB vector BX = CB[0] BY = CB[1] BZ = CB[2] ##Plane Parameters A = (AY * BZ) - (AZ * BY) B = (AZ * BX) - (AX * BZ) G = (AX * BY) - (AY * BX) ##Dot Product Constant F = math.sqrt(BX * BX + BY * BY + BZ * BZ) * L * math.cos( ang * (math.pi / 180.0)) ##Constants const = math.sqrt( math.pow((B * BZ - BY * G), 2) * (-(F * F) * (A * A + B * B + G * G) + (B * B * (BX * BX + BZ * BZ) + A * A * (BY * BY + BZ * BZ) - (2 * A * BX * BZ * G) + (BX * BX + BY * BY) * G * G - (2 * B * BY) * (A * BX + BZ * G)) * L * L)) denom = ((B * B) * (BX * BX + BZ * BZ) + (A * A) * (BY * BY + BZ * BZ) - (2 * A * BX * BZ * G) + (BX * BX + BY * BY) * (G * G) - (2 * B * BY) * (A * BX + BZ * G)) X = ((B * B * BX * F) - (A * B * BY * F) + (F * G) * (-A * BZ + BX * G) + const) / denom if (B == 0 or BZ == 0) and (BY == 0 or G == 0): const1 = math.sqrt(G * G * (-A * A * X * X + (B * B + G * G) * (L - X) * (L + X))) Y = ((-A * B * X) + const1) / (B * B + G * G) Z = -(A * G * G * X + B * const1) / (G * (B * B + G * G)) else: Y = ((A * A * BY * F) * (B * BZ - BY * G) + G * (-F * math.pow(B * BZ - BY * G, 2) + BX * const) - A * (B * B * BX * BZ * F - B * BX * BY * F * G + BZ * const)) / ( (B * BZ - BY * G) * denom) Z = ((A * A * BZ * F) * (B * BZ - BY * G) + (B * F) * math.pow(B * BZ - BY * G, 2) + (A * BX * F * G) * (-B * BZ + BY * G) - B * BX * const + A * BY * const) / ( (B * BZ - BY * G) * denom) # Get the new Vector from the origin D = Vector(X, Y, Z) + CV with warnings.catch_warnings(): # ignore inconsequential warning warnings.simplefilter("ignore") temp = calc_dihedral(AV, BV, CV, D) * (180.0 / math.pi) di = di - temp rot = rotaxis(math.pi * (di / 180.0), CV - BV) D = (D - BV).left_multiply(rot) + BV return D.get_array()
def process_tertiary(tertiary): '''compute the bond lengths, bond angles, and dihedral angles''' phi = [] psi = [] omega = [] bond_angle_CNCa = [] bond_angle_NCaC = [] bond_angle_CaCN = [] bond_len_NCa = [] bond_len_CaC = [] bond_len_CN = [] # convert tertiary coords into Vectors pV = [vec for vec in map(lambda v: Vector(v[0], v[1], v[2]), zip(tertiary[0], tertiary[1], tertiary[2]))] for i in range(0, len(pV), 3): # check for zero coords norm_im1 = False norm_i = False norm_i1 = False norm_i2 = False norm_i3 = False norm_i4 = False if i > 0 and pV[i-1].norm() > 0: norm_im1 = True if pV[i].norm() > 0: norm_i = True if pV[i+1].norm() > 0: norm_i1 = True if pV[i+2].norm() > 0: norm_i2 = True if i + 3 < len(pV) and pV[i+3].norm() > 0: norm_i3 = True if i + 3 < len(pV) and pV[i+4].norm() > 0: norm_i4 = True # compute bond lengths if norm_im1 and norm_i: blen_CN = (pV[i-1]-pV[i]).norm() bond_len_CN.append(blen_CN) if norm_i and norm_i1: blen_NCa = (pV[i]-pV[i+1]).norm() bond_len_NCa.append(blen_NCa) if norm_i1 and norm_i2: blen_CaC = (pV[i+1]-pV[i+2]).norm() bond_len_CaC.append(blen_CaC) # compute bond angles if norm_im1 and norm_i and norm_i1: theta_CNCa = calc_angle(pV[i-1], pV[i], pV[i+1]) # C-N-Ca bond_angle_CNCa.append(theta_CNCa) if norm_i and norm_i1 and norm_i2: theta_NCaC = calc_angle(pV[i], pV[i+1], pV[i+2]) # N-Ca-C bond_angle_NCaC.append(theta_NCaC) if norm_i1 and norm_i2 and norm_i3: theta_CaCN = calc_angle(pV[i+1], pV[i+2], pV[i+3]) # Ca-C-N bond_angle_CaCN.append(theta_CaCN) # compute dihedral angles if norm_im1 and norm_i and norm_i1 and norm_i2: phi_i = calc_dihedral( pV[i-1], pV[i], pV[i+1], pV[i+2]) # N-Ca-C-N else: phi_i = INVALID_ANGLE phi.append(phi_i) if norm_i and norm_i1 and norm_i2 and norm_i3: psi_i = calc_dihedral( pV[i], pV[i+1], pV[i+2], pV[i+3]) # C-N-Ca-C else: psi_i = INVALID_ANGLE psi.append(psi_i) if norm_i1 and norm_i2 and norm_i3 and norm_i4: omega_i = calc_dihedral( pV[i+1], pV[i+2], pV[i+3], pV[i+4]) # Ca-C-N-Ca else: omega_i = INVALID_ANGLE omega.append(omega_i) return (phi, psi, omega, bond_angle_NCaC, bond_angle_CaCN, bond_angle_CNCa, bond_len_CN, bond_len_NCa, bond_len_CaC)
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)
def test_division(self): """Confirm division works.""" v = Vector(1, 1, 1) / 2 self.assertEqual(repr(v), "<Vector 0.50, 0.50, 0.50>")