def compute_pi_cation(ligand, receptor): """ Computes number of pi-cation interactions. Returns a dictionary whose keys are of form ${MOLTYPE}-CHARGED_${STRUCTURE} where MOLTYPE is either "LIGAND" or "RECEPTOR" and STRUCTURE is "ALPHA" or "BETA" or "OTHER". Parameters ---------- ligand: PDB Object small molecule to dock. receptor: PDB Object protein to dock agains. """ pi_cation = { 'PI-CATION_LIGAND-CHARGED_ALPHA': 0, 'PI-CATION_LIGAND-CHARGED_BETA': 0, 'PI-CATION_LIGAND-CHARGED_OTHER': 0, 'PI-CATION_RECEPTOR-CHARGED_ALPHA': 0, 'PI-CATION_RECEPTOR-CHARGED_BETA': 0, 'PI-CATION_RECEPTOR-CHARGED_OTHER': 0} for aromatic in receptor.aromatic_rings: for charged in ligand.charges: if charged.positive == True: # so only consider positive charges if (charged.coordinates.dist_to(aromatic.center) < CATION_PI_CUTOFF): # project the charged onto the plane of the aromatic charge_projected = project_point_onto_plane( charged.coordinates,aromatic.plane_coeff) if (charge_projected.dist_to(aromatic.center) < aromatic.radius + PI_PADDING): structure = receptor.all_atoms[aromatic.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "PI-CATION_LIGAND-CHARGED_" + structure hashtable_entry_add_one(pi_cation, key) for aromatic in ligand.aromatic_rings: # now it's the ligand that has the aromatic group for charged in receptor.charges: if charged.positive == True: # so only consider positive charges if (charged.coordinates.dist_to(aromatic.center) < CATION_PI_CUTOFF): charge_projected = project_point_onto_plane( charged.coordinates,aromatic.plane_coeff) if (charge_projected.dist_to(aromatic.center) < aromatic.radius + PI_PADDING): structure = receptor.all_atoms[charged.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "PI-CATION_RECEPTOR-CHARGED_" + structure hashtable_entry_add_one(pi_cation, key) return pi_cation
def compute_pi_cation(ligand, receptor): """ Computes number of pi-cation interactions. Returns a dictionary whose keys are of form ${MOLTYPE}-CHARGED_${STRUCTURE} where MOLTYPE is either "LIGAND" or "RECEPTOR" and STRUCTURE is "ALPHA" or "BETA" or "OTHER". Parameters ---------- ligand: PDB Object small molecule to dock. receptor: PDB Object protein to dock agains. """ pi_cation = { 'PI-CATION_LIGAND-CHARGED_ALPHA': 0, 'PI-CATION_LIGAND-CHARGED_BETA': 0, 'PI-CATION_LIGAND-CHARGED_OTHER': 0, 'PI-CATION_RECEPTOR-CHARGED_ALPHA': 0, 'PI-CATION_RECEPTOR-CHARGED_BETA': 0, 'PI-CATION_RECEPTOR-CHARGED_OTHER': 0} for aromatic in receptor.aromatic_rings: for charged in ligand.charges: if charged.positive == True: # so only consider positive charges if charged.coordinates.dist_to(aromatic.center) < CATION_PI_CUTOFF: # project the charged onto the plane of the aromatic charge_projected = project_point_onto_plane( charged.coordinates, aromatic.plane_coeff) if (charge_projected.dist_to(aromatic.center) < aromatic.radius + PI_PADDING): structure = receptor.all_atoms[aromatic.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "PI-CATION_LIGAND-CHARGED_" + structure hashtable_entry_add_one(pi_cation, key) for aromatic in ligand.aromatic_rings: # now it's the ligand that has the aromatic group for charged in receptor.charges: if charged.positive: # so only consider positive charges if charged.coordinates.dist_to(aromatic.center) < CATION_PI_CUTOFF: charge_projected = project_point_onto_plane( charged.coordinates, aromatic.plane_coeff) if (charge_projected.dist_to(aromatic.center) < aromatic.radius + PI_PADDING): structure = receptor.all_atoms[charged.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "PI-CATION_RECEPTOR-CHARGED_" + structure hashtable_entry_add_one(pi_cation, key) return pi_cation
def test_project_point(self): """ TestPoint: Test that projection onto plane works. """ # First test with projection onto xy-plane value = project_point_onto_plane(Point(coords=np.array([1, 2, 3])), [0, 0, 1, 0]) assert np.array_equal(value.as_array(), np.array([1, 2, 0])) # Now test projection onto plane z = 4 value = project_point_onto_plane(Point(coords=np.array([1, 2, 3])), [0, 0, 1, 4]) assert np.array_equal(value.as_array(), np.array([1, 2, 4]))
def compute_pi_pi_stacking(ligand, receptor): """ Computes pi-pi interactions. Returns a dictionary with keys of form STACKING_${STRUCTURE} where STRUCTURE is "ALPHA" or "BETA" or "OTHER". Values are counts of the number of such stacking interactions. Parameters ---------- ligand: PDB Object. small molecule to dock. receptor: PDB Object protein to dock agains. """ pi_stacking = { 'STACKING_ALPHA': 0, 'STACKING_BETA': 0, 'STACKING_OTHER': 0 } for lig_aromatic in ligand.aromatic_rings: for rec_aromatic in receptor.aromatic_rings: dist = lig_aromatic.center.dist_to(rec_aromatic.center) if dist < PI_PI_CUTOFF: # so there could be some pi-pi interactions. Now, let's # check for stacking interactions. Are the two pi's roughly # parallel? lig_aromatic_norm_vector = Point(coords=np.array([ lig_aromatic.plane_coeff[0], lig_aromatic.plane_coeff[1], lig_aromatic.plane_coeff[2] ])) rec_aromatic_norm_vector = Point(coords=np.array([ rec_aromatic.plane_coeff[0], rec_aromatic.plane_coeff[1], rec_aromatic.plane_coeff[2] ])) angle_between_planes = (angle_between_points( lig_aromatic_norm_vector, rec_aromatic_norm_vector) * 180.0 / math.pi) if (math.fabs(angle_between_planes - 0) < 30.0 or math.fabs(angle_between_planes - 180) < 30.0): # so they're more or less parallel, it's probably pi-pi # stacking now, since pi-pi are not usually right on # top of each other. They're often staggered. So I don't # want to just look at the centers of the rings and # compare. Let's look at each of the atoms. do atom of # the atoms of one ring, when projected onto the plane of # the other, fall within that other ring? # start by assuming it's not a pi-pi stacking interaction pi_pi = False for ligand_ring_index in lig_aromatic.indices: # project the ligand atom onto the plane of the receptor ring pt_on_receptor_plane = project_point_onto_plane( ligand.all_atoms[ligand_ring_index].coordinates, rec_aromatic.plane_coeff) if (pt_on_receptor_plane.dist_to(rec_aromatic.center) <= rec_aromatic.radius + PI_PADDING): pi_pi = True break # TODO(rbharath): This if-else is confusing. if pi_pi == False: for receptor_ring_index in rec_aromatic.indices: # project the ligand atom onto the plane of the receptor ring pt_on_ligand_plane = project_point_onto_plane( receptor.all_atoms[receptor_ring_index]. coordinates, lig_aromatic.plane_coeff) if (pt_on_ligand_plane.dist_to(lig_aromatic.center) <= lig_aromatic.radius + PI_PADDING): pi_pi = True break if pi_pi == True: structure = receptor.all_atoms[ rec_aromatic.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "STACKING_" + structure hashtable_entry_add_one(pi_stacking, key) return pi_stacking
def compute_pi_t(ligand, receptor): """ Computes T-shaped pi-pi interactions. Returns a dictionary with keys of form T-SHAPED_${STRUCTURE} where STRUCTURE is "ALPHA" or "BETA" or "OTHER". Values are counts of the number of such stacking interactions. Parameters ---------- ligand: PDB Object. small molecule to dock. receptor: PDB Object protein to dock agains. """ pi_t = {'T-SHAPED_ALPHA': 0, 'T-SHAPED_BETA': 0, 'T-SHAPED_OTHER': 0} for lig_aromatic in ligand.aromatic_rings: for rec_aromatic in receptor.aromatic_rings: lig_aromatic_norm_vector = Point(coords=np.array([ lig_aromatic.plane_coeff[0], lig_aromatic.plane_coeff[1], lig_aromatic.plane_coeff[2] ])) rec_aromatic_norm_vector = Point(coords=np.array([ rec_aromatic.plane_coeff[0], rec_aromatic.plane_coeff[1], rec_aromatic.plane_coeff[2] ])) angle_between_planes = (angle_between_points( lig_aromatic_norm_vector, rec_aromatic_norm_vector) * 180.0 / math.pi) if (math.fabs(angle_between_planes - 90) < 30.0 or math.fabs(angle_between_planes - 270) < 30.0): # so they're more or less perpendicular, it's probably a # pi-edge interaction having looked at many structures, I # noticed the algorithm was identifying T-pi reactions # when the two rings were in fact quite distant, often # with other atoms in between. Eye-balling it, requiring # that at their closest they be at least 5 A apart seems # to separate the good T's from the bad min_dist = 100.0 for ligand_ind in lig_aromatic.indices: ligand_at = ligand.all_atoms[ligand_ind] for receptor_ind in rec_aromatic.indices: receptor_at = receptor.all_atoms[receptor_ind] dist = ligand_at.coordinates.dist_to( receptor_at.coordinates) if dist < min_dist: min_dist = dist if min_dist <= 5.0: # so at their closest points, the two rings come within # 5 A of each other. # okay, is the ligand pi pointing into the receptor # pi, or the other way around? first, project the # center of the ligand pi onto the plane of the # receptor pi, and vs. versa # This could be directional somehow, like a hydrogen # bond. pt_on_receptor_plane = project_point_onto_plane( lig_aromatic.center, rec_aromatic.plane_coeff) pt_on_ligand_plane = project_point_onto_plane( rec_aromatic.center, lig_aromatic.plane_coeff) # now, if it's a true pi-T interaction, this projected # point should fall within the ring whose plane it's # been projected into. if ((pt_on_receptor_plane.dist_to(rec_aromatic.center) <= rec_aromatic.radius + PI_PADDING) or (pt_on_ligand_plane.dist_to(lig_aromatic.center) <= lig_aromatic.radius + PI_PADDING)): # so it is in the ring on the projected plane. structure = receptor.all_atoms[ rec_aromatic.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "T-SHAPED_" + structure hashtable_entry_add_one(pi_t, key) return pi_t
def compute_pi_pi_stacking(ligand, receptor): """ Computes pi-pi interactions. Returns a dictionary with keys of form STACKING_${STRUCTURE} where STRUCTURE is "ALPHA" or "BETA" or "OTHER". Values are counts of the number of such stacking interactions. Parameters ---------- ligand: PDB Object. small molecule to dock. receptor: PDB Object protein to dock agains. """ pi_stacking = {'STACKING_ALPHA': 0, 'STACKING_BETA': 0, 'STACKING_OTHER': 0} for lig_aromatic in ligand.aromatic_rings: for rec_aromatic in receptor.aromatic_rings: dist = lig_aromatic.center.dist_to(rec_aromatic.center) if dist < PI_PI_CUTOFF: # so there could be some pi-pi interactions. Now, let's # check for stacking interactions. Are the two pi's roughly # parallel? lig_aromatic_norm_vector = Point( coords=np.array([lig_aromatic.plane_coeff[0], lig_aromatic.plane_coeff[1], lig_aromatic.plane_coeff[2]])) rec_aromatic_norm_vector = Point( coords=np.array([rec_aromatic.plane_coeff[0], rec_aromatic.plane_coeff[1], rec_aromatic.plane_coeff[2]])) angle_between_planes = (angle_between_points( lig_aromatic_norm_vector, rec_aromatic_norm_vector) * 180.0/math.pi) if (math.fabs(angle_between_planes-0) < 30.0 or math.fabs(angle_between_planes-180) < 30.0): # so they're more or less parallel, it's probably pi-pi # stacking now, since pi-pi are not usually right on # top of each other. They're often staggered. So I don't # want to just look at the centers of the rings and # compare. Let's look at each of the atoms. do atom of # the atoms of one ring, when projected onto the plane of # the other, fall within that other ring? # start by assuming it's not a pi-pi stacking interaction pi_pi = False for ligand_ring_index in lig_aromatic.indices: # project the ligand atom onto the plane of the receptor ring pt_on_receptor_plane = project_point_onto_plane( ligand.all_atoms[ligand_ring_index].coordinates, rec_aromatic.plane_coeff) if (pt_on_receptor_plane.dist_to(rec_aromatic.center) <= rec_aromatic.radius + PI_PADDING): pi_pi = True break # TODO(rbharath): This if-else is confusing. if pi_pi == False: for receptor_ring_index in rec_aromatic.indices: # project the ligand atom onto the plane of the receptor ring pt_on_ligand_plane = project_point_onto_plane( receptor.all_atoms[receptor_ring_index].coordinates, lig_aromatic.plane_coeff) if (pt_on_ligand_plane.dist_to(lig_aromatic.center) <= lig_aromatic.radius + PI_PADDING): pi_pi = True break if pi_pi == True: structure = receptor.all_atoms[rec_aromatic.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "STACKING_" + structure hashtable_entry_add_one(pi_stacking, key) return pi_stacking
def compute_pi_t(ligand, receptor): """ Computes T-shaped pi-pi interactions. Returns a dictionary with keys of form T-SHAPED_${STRUCTURE} where STRUCTURE is "ALPHA" or "BETA" or "OTHER". Values are counts of the number of such stacking interactions. Parameters ---------- ligand: PDB Object. small molecule to dock. receptor: PDB Object protein to dock agains. """ pi_t = {'T-SHAPED_ALPHA': 0, 'T-SHAPED_BETA': 0, 'T-SHAPED_OTHER': 0} for lig_aromatic in ligand.aromatic_rings: for rec_aromatic in receptor.aromatic_rings: lig_aromatic_norm_vector = Point( coords=np.array([lig_aromatic.plane_coeff[0], lig_aromatic.plane_coeff[1], lig_aromatic.plane_coeff[2]])) rec_aromatic_norm_vector = Point( coords=np.array([rec_aromatic.plane_coeff[0], rec_aromatic.plane_coeff[1], rec_aromatic.plane_coeff[2]])) angle_between_planes = (angle_between_points( lig_aromatic_norm_vector, rec_aromatic_norm_vector) * 180.0/math.pi) if (math.fabs(angle_between_planes-90) < 30.0 or math.fabs(angle_between_planes-270) < 30.0): # so they're more or less perpendicular, it's probably a # pi-edge interaction having looked at many structures, I # noticed the algorithm was identifying T-pi reactions # when the two rings were in fact quite distant, often # with other atoms in between. Eye-balling it, requiring # that at their closest they be at least 5 A apart seems # to separate the good T's from the bad min_dist = 100.0 for ligand_ind in lig_aromatic.indices: ligand_at = ligand.all_atoms[ligand_ind] for receptor_ind in rec_aromatic.indices: receptor_at = receptor.all_atoms[receptor_ind] dist = ligand_at.coordinates.dist_to(receptor_at.coordinates) if dist < min_dist: min_dist = dist if min_dist <= 5.0: # so at their closest points, the two rings come within # 5 A of each other. # okay, is the ligand pi pointing into the receptor # pi, or the other way around? first, project the # center of the ligand pi onto the plane of the # receptor pi, and vs. versa # This could be directional somehow, like a hydrogen # bond. pt_on_receptor_plane = project_point_onto_plane( lig_aromatic.center, rec_aromatic.plane_coeff) pt_on_ligand_plane = project_point_onto_plane( rec_aromatic.center, lig_aromatic.plane_coeff) # now, if it's a true pi-T interaction, this projected # point should fall within the ring whose plane it's # been projected into. if ((pt_on_receptor_plane.dist_to(rec_aromatic.center) <= rec_aromatic.radius + PI_PADDING) or (pt_on_ligand_plane.dist_to(lig_aromatic.center) <= lig_aromatic.radius + PI_PADDING)): # so it is in the ring on the projected plane. structure = receptor.all_atoms[rec_aromatic.indices[0]].structure if structure == "": # since it could be interacting with a cofactor or something structure = "OTHER" key = "T-SHAPED_" + structure hashtable_entry_add_one(pi_t, key) return pi_t