Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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