Exemple #1
0
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]
Exemple #2
0
 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()))
Exemple #3
0
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
Exemple #4
0
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)
Exemple #5
0
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)