Ejemplo n.º 1
0
 def assert_equal_matrices(array, matrix1, matrix2, periodic):
     """
     Due to numerical instability, entries in both matrices might
     be different, when the distance of atoms is almost equal to
     the cutoff distance of the matrix.
     This function checks, whether two atoms with unequal entries
     in the matrices are near the cutoff distance.
     """
     nonlocal CUTOFF
     indices = np.where(matrix1 != matrix2)
     for index in range(len(indices[0])):
         if len(indices) == 2:
             # multi_model = False -> AtomArray
             m = None
             i = indices[0][index]
             j = indices[1][index]
             box = array.box if periodic else None
             distance = struc.distance(array[i], array[j], box=box)
         if len(indices) == 3:
             # multi_model = True -> AtomArrayStack
             m = indices[0][index]
             i = indices[1][index]
             j = indices[2][index]
             box = array.box[m] if periodic else None
             distance = struc.distance(array[m, i], array[m, j], box=box)
         try:
             assert distance == pytest.approx(CUTOFF, abs=1e-4)
         except AssertionError:
             print(f"Model {m}, Atoms {i} and {j}")
             raise
Ejemplo n.º 2
0
def test_masked_superimposition(seed):
    """
    Take two models of the same structure and superimpose based on a
    single, randomly chosen atom.
    Since two atoms can be superimposed perfectly, the distance between
    the atom in both models should be 0.
    """

    path = join(data_dir, "1l2y.mmtf")
    fixed = strucio.load_structure(path, model=1)
    mobile = strucio.load_structure(path, model=2)

    # Create random mask for a single atom
    np.random.seed(seed)
    mask = np.full(fixed.array_length(), False)
    mask[np.random.randint(fixed.array_length())] = True

    # The distance between the atom in both models should not be
    # already 0 prior to superimposition
    assert struc.distance(fixed[mask], mobile[mask])[0] \
        != pytest.approx(0, abs=5e-4)

    fitted, transformation = struc.superimpose(fixed, mobile, mask)

    assert struc.distance(fixed[mask], fitted[mask])[0] \
        == pytest.approx(0, abs=5e-4)

    fitted = struc.superimpose_apply(mobile, transformation)

    struc.distance(fixed[mask], fitted[mask])[0] \
        == pytest.approx(0, abs=5e-4)
Ejemplo n.º 3
0
def membrane_thickness(upper_atoms, lower_atoms):
    """ Calculate membrane thickness. For each atom, the algorithm calculates
    the distance to the closest atom in the other leaflet.

    Parameters
    ----------
    upper_atoms, lower_atoms : AtomArray or AtomArrayStack
        atoms of the lower and upper membrane leaflet to use for distance
        calculation

    Returns
    -------
    ndarray
        For each frame, a set of x and y coordinates and the corresponding
        membrane thickness is returned

    """
    if not isinstance(lower_atoms, AtomArrayStack):
        lower_atoms = stack([lower_atoms])
    if not isinstance(upper_atoms, AtomArrayStack):
        upper_atoms = stack([upper_atoms])

    thickness_upper = np.full(
        [len(upper_atoms), upper_atoms.array_length(), 3], 0.0)
    thickness_lower = np.full(
        [len(lower_atoms), lower_atoms.array_length(), 3], 0.0)
    for idx in range(upper_atoms.array_length()):
        atom = upper_atoms[:, idx]
        dist = struct.distance(atom, lower_atoms)

        atom_min_dist = dist.min(axis=1)

        thickness_upper[:, idx, 0:2] = atom.coord[:, 0, 0:2]
        thickness_upper[:, idx, -1] = atom_min_dist

    for idx in range(lower_atoms.array_length()):
        atom = lower_atoms[:, idx]
        dist = struct.distance(atom, upper_atoms)

        atom_min_dist = dist.min(axis=1)

        thickness_lower[:, idx, 0:2] = atom.coord[:, 0, 0:2]
        thickness_lower[:, idx, -1] = atom_min_dist

    thickness = np.concatenate([thickness_upper, thickness_lower], axis=1)

    if thickness.shape[0] == 1:
        return thickness[0, ...]
    else:
        return thickness
Ejemplo n.º 4
0
def test_index_functions():
    """
    The `index_xxx()` functions should give the same result as the
    corresponding `xxx` functions.
    """
    stack = strucio.load_structure(join(data_dir, "1l2y.mmtf"))
    array = stack[0]
    # Test for atom array, stack and raw coordinates
    samples = (array, stack, struc.coord(array), struc.coord(stack))
    # Generate random indices
    random.seed(42)
    indices = random.randint(array.array_length(), size=(100, 4), dtype=int)
    for sample in samples:
        if isinstance(sample, np.ndarray):
            atoms1 = sample[..., indices[:, 0], :]
            atoms2 = sample[..., indices[:, 1], :]
            atoms3 = sample[..., indices[:, 2], :]
            atoms4 = sample[..., indices[:, 3], :]
        else:
            atoms1 = sample[..., indices[:, 0]]
            atoms2 = sample[..., indices[:, 1]]
            atoms3 = sample[..., indices[:, 2]]
            atoms4 = sample[..., indices[:, 3]]
        assert np.allclose(struc.displacement(atoms1, atoms2),
                           struc.index_displacement(sample, indices[:, :2]),
                           atol=1e-5)
        assert np.allclose(struc.distance(atoms1, atoms2),
                           struc.index_distance(sample, indices[:, :2]),
                           atol=1e-5)
        assert np.allclose(struc.angle(atoms1, atoms2, atoms3),
                           struc.index_angle(sample, indices[:, :3]),
                           atol=1e-5)
        assert np.allclose(struc.dihedral(atoms1, atoms2, atoms3, atoms4),
                           struc.index_dihedral(sample, indices[:, :4]),
                           atol=1e-5)
Ejemplo n.º 5
0
def detect_disulfide_bonds(structure,
                           distance=2.05,
                           distance_tol=0.05,
                           dihedral=90,
                           dihedral_tol=10):
    # Array where detected disulfide bonds are stored
    disulfide_bonds = []
    # A mask that selects only S-gamma atoms of cysteins
    sulfide_mask = (structure.res_name == "CYS") & \
                   (structure.atom_name == "SG")
    # sulfides in adjacency to other sulfides are detected in an
    # efficient manner via a cell list
    cell_list = struc.CellList(structure,
                               cell_size=distance + distance_tol,
                               selection=sulfide_mask)
    # Iterate over every index corresponding to an S-gamma atom
    for sulfide_i in np.where(sulfide_mask)[0]:
        # Find indices corresponding to other S-gamma atoms,
        # that are adjacent to the position of structure[sulfide_i]
        # We use the faster 'get_atoms_in_cells()' instead of
        # `get_atoms()`, as precise distance measurement is done
        # afterwards anyway
        potential_bond_partner_indices = cell_list.get_atoms_in_cells(
            coord=structure.coord[sulfide_i])
        # Iterate over every index corresponding to an S-gamma atom
        # as bond partner
        for sulfide_j in potential_bond_partner_indices:
            if sulfide_i == sulfide_j:
                # A sulfide cannot create a bond with itself:
                continue
            # Create 'Atom' instances
            # of the potentially bonds S-gamma atoms
            sg1 = structure[sulfide_i]
            sg2 = structure[sulfide_j]
            # For dihedral angle measurement the corresponding
            # C-beta atoms are required, too
            cb1 = structure[(structure.chain_id == sg1.chain_id)
                            & (structure.res_id == sg1.res_id) &
                            (structure.atom_name == "CB")]
            cb2 = structure[(structure.chain_id == sg2.chain_id)
                            & (structure.res_id == sg2.res_id) &
                            (structure.atom_name == "CB")]
            # Measure distance and dihedral angle and check criteria
            bond_dist = struc.distance(sg1, sg2)
            bond_dihed = np.abs(np.rad2deg(struc.dihedral(cb1, sg1, sg2, cb2)))
            if bond_dist  > distance - distance_tol and \
               bond_dist  < distance + distance_tol and \
               bond_dihed > dihedral - dihedral_tol and \
               bond_dihed < dihedral + dihedral_tol:
                # Atom meet criteria -> we found a disulfide bond
                # -> the indices of the bond S-gamma atoms
                # are put into a tuple with the lower index first
                bond_tuple = sorted((sulfide_i, sulfide_j))
                # Add bond to list of bonds, but each bond only once
                if bond_tuple not in disulfide_bonds:
                    disulfide_bonds.append(bond_tuple)
    return np.array(disulfide_bonds, dtype=int)
Ejemplo n.º 6
0
def test_index_distance_non_periodic():
    """
    Without PBC the result should be equal to the normal distance
    calculation.
    """
    array = strucio.load_structure(join(data_dir, "3o5r.mmtf"))
    ref_dist = struc.distance(array.coord[np.newaxis, :, :],
                              array.coord[:, np.newaxis, :]).flatten()
    length = array.array_length()
    dist = struc.index_distance(array,
                                indices=np.stack([
                                    np.repeat(np.arange(length), length),
                                    np.tile(np.arange(length), length)
                                ],
                                                 axis=1))
    assert np.allclose(dist, ref_dist)
Ejemplo n.º 7
0
                                                    root=atom_i)

        accepted = False
        while not accepted:
            # A random angle between 0 and 360 degrees
            angle = np.random.rand() * 2 * np.pi
            # Rotate
            coord[rotated_atom_indices] = struc.rotate_about_axis(
                coord[rotated_atom_indices], axis, angle, support)

            # Check if the atoms clash with each other:
            # The distance between each pair of atoms must be larger
            # than the sum of their VdW radii, if they are not bonded to
            # each other
            accepted = True
            distances = struc.distance(coord[:, np.newaxis],
                                       coord[np.newaxis, :])
            clashed = distances < vdw_radii_mean
            for clash_atom1, clash_atom2 in zip(*np.where(clashed)):
                if clash_atom1 == clash_atom2:
                    # Ignore distance of an atom to itself
                    continue
                if (clash_atom1, clash_atom2) not in bond_list:
                    # Nonbonded atoms clash
                    # -> structure is not accepted
                    accepted = False
    rotamer_coord[i] = coord
rotamers = struc.from_template(residue, rotamer_coord)

### Superimpose backbone onto first model for better visualization ###
rotamers, _ = struc.superimpose(rotamers[0],
                                rotamers,
Ejemplo n.º 8
0
def extractInterface(dimer, c1, c2, vdwC, minC, nearC, mem):
    """
    This function extracts interfaces from provided dimers, by chain ids.
    """

    if os.path.exists("cache.hdf5"):
        os.remove("cache.hdf5")
    
    vdw_dict = {'ALA': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.165, 'C': 1.87, 'O': 1.55}, 'ARG': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'CD': 2.235, 'NE': 1.83, 'HE': 0.8, 'CZ': 1.87, 'NH1': 1.83, 'HH11': 0.6, 'HH12': 0.6, 'NH2': 1.83, 'HH21': 0.6, 'HH22': 0.6, 'C': 1.87, 'O': 1.55}, 'ARGN': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'CD': 2.235, 'NE': 1.83, 'HE': 0.8, 'CZ': 1.87, 'NH1': 1.83, 'HH11': 0.6, 'HH12': 0.6, 'NH2': 1.83, 'HH21': 0.6, 'C': 1.87, 'O': 1.55}, 'ASN': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 1.87, 'OD1': 1.55, 'ND2': 1.83, 'HD21': 0.8, 'HD22': 0.8, 'C': 1.87, 'O': 1.55, 'AD1': 1.55, 'AD2': 1.83}, 'ASP': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 1.87, 'OD1': 1.66, 'OD2': 1.66, 'C': 1.87, 'O': 1.55}, 'ASPH': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 1.87, 'OD1': 1.52, 'OD2': 1.55, 'HD': 0.8, 'C': 1.87, 'O': 1.55}, 'CYS': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'SG': 1.89, 'C': 1.87, 'O': 1.55}, 'GLN': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'CD': 1.87, 'OE1': 1.55, 'NE2': 1.83, 'HE21': 0.8, 'HE22': 0.8, 'C': 1.87, 'O': 1.55, 'AE1': 1.55, 'AE2': 1.83}, 'GLU': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'CD': 1.87, 'OE1': 1.66, 'OE2': 1.66, 'C': 1.87, 'O': 1.55}, 'GLUH': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'CD': 1.87, 'OE1': 1.52, 'OE2': 1.55, 'HE': 0.8, 'C': 1.87, 'O': 1.55}, 'GLY': {'N': 1.83, 'H': 0.8, 'CA': 2.235, 'C': 1.87, 'O': 1.55}, 'HIS': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.04, 'ND1': 1.72, 'HD1': 0.8, 'CD2': 2.1, 'NE2': 1.72, 'CE1': 2.1, 'C': 1.87, 'O': 1.55, 'AE1': 2.1, 'AE2': 1.72}, 'ILE': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.265, 'CG2': 2.165, 'CG1': 2.235, 'CD1': 2.165, 'C': 1.87, 'O': 1.55, 'CD': 2.165}, 'LEU': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.265, 'CD1': 2.165, 'CD2': 2.165, 'C': 1.87, 'O': 1.55}, 'LYS': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'CD': 2.235, 'CE': 2.235, 'NZ': 1.65, 'HZ': 0.6, 'HZ1': 0.6, 'HZ2': 0.6, 'HZ3': 0.6, 'C': 1.87, 'O': 1.55}, 'LYSN': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'CD': 2.235, 'CE': 2.235, 'NZ': 1.65, 'HZ1': 0.8, 'HZ2': 0.8, 'C': 1.87, 'O': 1.55}, 'MET': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'SD': 1.97, 'CE': 2.165, 'C': 1.87, 'O': 1.55}, 'PHE': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.04, 'CD1': 1.99, 'CD2': 1.99, 'CE1': 1.99, 'CE2': 1.99, 'CZ': 1.99, 'C': 1.87, 'O': 1.55}, 'PRO': {'N': 1.83, 'CD': 2.235, 'CA': 2.265, 'CB': 2.235, 'CG': 2.235, 'C': 1.87, 'O': 1.55}, 'SER': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'OG': 1.55, 'HG': 0.76, 'C': 1.87, 'O': 1.55}, 'THR': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.265, 'OG1': 1.55, 'HG1': 0.76, 'CG2': 2.165, 'C': 1.87, 'O': 1.55}, 'TRP': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.04, 'CD2': 2.04, 'CE2': 2.04, 'CE3': 1.99, 'CD1': 2.1, 'NE1': 1.72, 'HE1': 0.8, 'CZ2': 1.99, 'CZ3': 1.99, 'CH2': 1.99, 'C': 1.87, 'O': 1.55}, 'TYR': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.04, 'CD1': 1.99, 'CE1': 1.99, 'CD2': 1.99, 'CE2': 1.99, 'CZ': 2.04, 'OH': 1.55, 'HH': 0.76, 'C': 1.87, 'O': 1.55}, 'VAL': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.265, 'CG1': 2.165, 'CG2': 2.165, 'C': 1.87, 'O': 1.55}, 'HSC': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.04, 'CD2': 2.1, 'ND1': 1.72, 'HD1': 0.8, 'CE1': 2.1, 'NE2': 1.72, 'HE2': 0.8, 'C': 1.87, 'O': 1.55}, 'HSD': {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.235, 'CG': 2.04, 'ND1': 1.72, 'CE1': 2.1, 'CD2': 2.1, 'NE2': 1.72, 'HE2': 0.8, 'C': 1.87, 'O': 1.55}, 'ACE': {'C': 1.87, 'O': 1.55, 'CH3': 2.165}}
    default_dict = {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.265, 'C': 1.87, 'O': 1.55, 'CG': 2.265, 'CD': 2.235, 'NE': 1.83, 'HE': 0.8, 'C1': 1.87, 'C2': 1.87, 'C3': 1.87, 'CZ': 2.04, 'NH1': 1.83, 'H1': 0.8, 'H2': 0.8, 'H3': 0.8, 'H11': 0.8, 'H12': 0.8, 'H31': 0.8, 'H32': 0.8, 'HA' : 0.8, 'HA2' : 0.8, 'HA3' : 0.8, 'HB' : 0.8, 'HB1' : 0.8, 'HB2' : 0.8, 'HB3' : 0.8, 'HH2': 0.6, 'HH11': 0.6, 'HH12': 0.6, 'NH2': 1.83, 'HH21': 0.6, 'HH22': 0.6, 'OD1': 1.66, 'ND2': 1.83, 'HD21': 0.8, 'HD22': 0.8, 'AD1': 1.55, 'AD2': 1.83, 'OD2': 1.66, 'HD': 0.8, 'SG': 1.89, 'OE1': 1.66, 'NE2': 1.83, 'HE2': 0.8, 'HE3': 0.8, 'HE21': 0.8, 'HE22': 0.8, 'AE1': 2.1, 'AE2': 1.83, 'OE2': 1.66, 'ND1': 1.72, 'HD1': 0.8, 'HD2': 0.8, 'HD3': 0.8, 'HD11': 0.8, 'HD12': 0.8, 'HD13': 0.8, 'HD23': 0.8, 'CD2': 2.165, 'CE1': 2.1, 'CG2': 2.165, 'CG1': 2.235, 'CD1': 2.165, 'CE': 2.235, 'NZ': 1.65, 'HZ': 0.6, 'HZ1': 0.8, 'HZ2': 0.8, 'HZ3': 0.6, 'SD': 1.97, 'CE2': 2.04, 'OG': 1.55, 'HG': 0.76, 'OG1': 1.55, 'HG1': 0.76, 'HG2': 0.76, 'HG3': 0.76, 'HG11': 0.76, 'HG12': 0.76, 'HG13': 0.76, 'HG21': 0.76, 'HG22': 0.76, 'HG23': 0.76, 'CE3': 1.99, 'NE1': 1.72, 'HE1': 0.8, 'HO1': 0.8, 'HO2': 0.8, 'HO3': 0.8, 'CZ2': 1.99, 'CZ3': 1.99, 'CH2': 1.99, 'OH': 1.55, 'OXT': 1.55, 'O1': 1.55, 'O2': 1.55, 'O3': 1.55, 'HH': 0.76, 'HE2': 0.8, 'CH3': 2.165}
    no_digit_dict = {'N': 1.83, 'H': 0.8, 'CA': 2.265, 'CB': 2.265, 'C': 1.87, 'O': 1.55, 'CG': 2.265, 'CD': 2.235, 'NE': 1.83, 'HE': 0.8, 'CZ': 2.04, 'NH': 1.83, 'HA': 0.8, 'HB': 0.8, 'HH': 0.76, 'OD': 1.66, 'ND': 1.83, 'HD': 0.8, 'AD': 1.83, 'SG': 1.89, 'OE': 1.66, 'AE': 2.1, 'CE': 2.235, 'NZ': 1.65, 'HZ': 0.8, 'SD': 1.97, 'OG': 1.55, 'HG': 0.76, 'HO': 0.8, 'CH': 2.165, 'OH': 1.55, 'OXT': 1.55, 'D': 0.8, 'DZ': 0.8, 'HXT': 0.8, 'HAB': 0.8}

    chain_1 = dimer[dimer.chain_id == c1]
    chain_2 = dimer[dimer.chain_id == c2]

    chain_1_coord = chain_1.coord
    chain_2_coord = chain_2.coord

    try:
        chain_1_vdw = [float(vdw_dict[chain_1[i].res_name][chain_1[i].atom_name]) for i in range(len(chain_1))]

    except:
        chain_1_vdw = []

        for i in range(len(chain_1)):

            if chain_1[i].res_name in vdw_dict and chain_1[i].atom_name in vdw_dict[chain_1[i].res_name]:
                chain_1_vdw.append(float(vdw_dict[chain_1[i].res_name][chain_1[i].atom_name]))

            elif chain_1[i].atom_name in default_dict:
                chain_1_vdw.append(float(default_dict[chain_1[i].atom_name]))

            else:
                chain_1_vdw.append(float(no_digit_dict[chain_1[''.join([j for j in chain_1[i].atom_name if not j.isdigit()])].atom_name]))

    try:
        chain_2_vdw = [float(vdw_dict[chain_2[i].res_name][chain_2[i].atom_name]) for i in range(len(chain_2))]

    except:
        chain_2_vdw = []

        for i in range(len(chain_2)):

            if chain_2[i].res_name in vdw_dict and chain_2[i].atom_name in vdw_dict[chain_2[i].res_name]:
                chain_2_vdw.append(float(vdw_dict[chain_2[i].res_name][chain_2[i].atom_name]))

            elif chain_2[i].atom_name in default_dict:
                chain_2_vdw.append(float(default_dict[chain_2[i].atom_name]))

            else:
                chain_2_vdw.append(float(no_digit_dict[chain_2[''.join([j for j in chain_1[i].atom_name if not j.isdigit()])].atom_name]))

    if len(chain_1) * len(chain_2) * 8 > mem * (1024**3)/3:

        hdf5_file = True

        hdf5_store = h5py.File("cache.hdf5", "a")

        critdist_array = hdf5_store.create_dataset("critdist_array", (len(chain_1), len(chain_2)))
        n = len(chain_2)
        chunks = 10

        chunk_size = [[i * int(n / chunks), (i + 1) * int(n / chunks)] if i + 1 != chunks else [i * int(n / chunks), n]
                      for i in range(chunks)]

        for start, end in chunk_size:
            critdist_array[:, start:end] = np.array(chain_2_vdw[start:end]) + np.array(chain_1_vdw).reshape((-1, 1)) + vdwC

        realdist_array = hdf5_store.create_dataset('realdist_array', data=cdist(chain_1_coord, chain_2_coord, 'euclidean'))

        contacting_bool = np.zeros(realdist_array.shape, dtype=bool)

        n = len(realdist_array)
        chunks = 500

        chunk_size = [[i * int(n / chunks), (i + 1) * int(n / chunks)] if i + 1 != chunks else [i * int(n / chunks), n]
                      for i in range(chunks)]

        for start, end in chunk_size:
            contacting_bool[start:end, :] = realdist_array[start:end] <= critdist_array[start:end]

        contacting_1 = np.unique(chain_1[np.any(contacting_bool, axis=1)].res_id)
        contacting_2 = np.unique(chain_2[np.any(contacting_bool, axis=0)].res_id)

    else:

        hdf5_file = False

        realdist_array = cdist(chain_1_coord, chain_2_coord, 'euclidean')
        critdist_array = np.array(chain_2_vdw) + np.array(chain_1_vdw).reshape((-1, 1)) + vdwC

        contacting_1 = np.unique(chain_1[np.any(realdist_array <= critdist_array, axis=1)].res_id)
        contacting_2 = np.unique(chain_2[np.any(realdist_array <= critdist_array, axis=0)].res_id)

    if len(contacting_1) < minC or len(contacting_2) < minC:

        if hdf5_file is True:
            hdf5_store.close()
            os.remove("cache.hdf5")

        return None

    contacting = dimer[np.logical_or(np.logical_and(dimer.chain_id == c1, np.isin(dimer.res_id, contacting_1)), 
                                     np.logical_and(dimer.chain_id == c2, np.isin(dimer.res_id, contacting_2)))]

    contacting_ca = contacting[contacting.atom_name == 'CA']
    dimer_ca = dimer[dimer.atom_name == 'CA']
    pos_nearby_ca = dimer_ca[~struc.filter_intersection(dimer_ca, contacting_ca)]
    nearby_array = np.zeros((len(pos_nearby_ca), len(contacting_ca)))

    for i in range(len(pos_nearby_ca)):
        nearby_array[i] = struc.distance(pos_nearby_ca[i], contacting_ca)

    nearby_ca = pos_nearby_ca[np.any(nearby_array <= nearC, axis = 1)]

    nearby_1 = nearby_ca[nearby_ca.chain_id == c1].res_id
    nearby_2 = nearby_ca[nearby_ca.chain_id == c2].res_id

    nearby = dimer[np.logical_or(np.logical_and(dimer.chain_id == c1, np.isin(dimer.res_id, nearby_1)), 
                                 np.logical_and(dimer.chain_id == c2, np.isin(dimer.res_id, nearby_2)))]

    interface_1 = sorted(list(contacting_1) + list(nearby_1))
    interface_2 = sorted(list(contacting_2) + list(nearby_2))

    interface = dimer[np.logical_or(np.logical_and(dimer.chain_id == c1, np.isin(dimer.res_id, interface_1)), 
                                    np.logical_and(dimer.chain_id == c2, np.isin(dimer.res_id, interface_2)))]

    if hdf5_file is True:
        hdf5_store.close()
        os.remove("cache.hdf5")
    
    return ", ".join(map(str, contacting_1)), ", ".join(map(str, contacting_2)), ", ".join(map(str, nearby_1)), ", ".join(map(str, nearby_2)), interface
Ejemplo n.º 9
0
def test_distance():
    coord1 = struc.coord([0, 1, 1])
    coord2 = struc.coord([0, 2, 2])
    assert struc.distance(coord1, coord2) == pytest.approx(np.sqrt(2))
Ejemplo n.º 10
0
def test_docking(flexible):
    """
    Test :class:`VinaApp` for the case of docking biotin to
    streptavidin.
    The output binding pose should be very similar to the pose in the
    PDB structure.
    """
    # A structure of a straptavidin-biotin complex
    mmtf_file = mmtf.MMTFFile.read(join(data_dir("application"), "2rtg.mmtf"))
    structure = mmtf.get_structure(mmtf_file,
                                   model=1,
                                   extra_fields=["charge"],
                                   include_bonds=True)
    structure = structure[structure.chain_id == "B"]
    receptor = structure[struc.filter_amino_acids(structure)]
    ref_ligand = structure[structure.res_name == "BTN"]
    ref_ligand_coord = ref_ligand.coord

    ligand = info.residue("BTN")
    # Remove hydrogen atom that is missing in ref_ligand
    ligand = ligand[ligand.atom_name != "HO2"]

    if flexible:
        # Two residues within the binding pocket: ASN23, SER88
        flexible_mask = np.isin(receptor.res_id, (23, 88))
    else:
        flexible_mask = None

    app = VinaApp(ligand,
                  receptor,
                  struc.centroid(ref_ligand), [20, 20, 20],
                  flexible=flexible_mask)
    app.set_seed(0)
    app.start()
    app.join()

    test_ligand_coord = app.get_ligand_coord()
    test_receptor_coord = app.get_receptor_coord()
    energies = app.get_energies()
    # One energy value per model
    assert len(test_ligand_coord) == len(energies)
    assert len(test_receptor_coord) == len(energies)

    assert np.all(energies < 0)

    # Select best binding pose
    test_ligand_coord = test_ligand_coord[0]
    not_nan_mask = ~np.isnan(test_ligand_coord).any(axis=-1)
    ref_ligand_coord = ref_ligand_coord[not_nan_mask]
    test_ligand_coord = test_ligand_coord[not_nan_mask]
    # Check if it least one atom is preserved
    assert test_ligand_coord.shape[1] > 0
    rmsd = struc.rmsd(ref_ligand_coord, test_ligand_coord)
    # The deviation of the best pose from the real conformation
    # should be less than 1 Å
    assert rmsd < 1.0

    if flexible:
        # Select best binding pose
        test_receptor_coord = test_receptor_coord[0]
        not_nan_mask = ~np.isnan(test_receptor_coord).any(axis=-1)
        ref_receptor_coord = receptor[not_nan_mask]
        test_receptor_coord = test_receptor_coord[not_nan_mask]
        # Check if it least one atom is preserved
        assert test_receptor_coord.shape[1] > 0
        # The flexible residues should have a maximum deviation of 1 Å
        # from the original conformation
        assert np.max(struc.distance(test_receptor_coord,
                                     ref_receptor_coord)) < 1.0
    else:
        ref_receptor_coord = receptor.coord
        for model_coord in test_receptor_coord:
            assert np.array_equal(model_coord, ref_receptor_coord)
Ejemplo n.º 11
0
# Style protein
protein_mask = struc.filter_amino_acids(cyt_c)

pymol_cyt_c.show_as("cartoon", protein_mask)
pymol_cyt_c.color("lightgreen", protein_mask & (cyt_c.element == "C"))

#----------------------------------------------------------------------#

# Style heme group
heme_mask = (cyt_c.res_name == "HEM")

pymol_cyt_c.show_as("sticks", heme_mask)
pymol_cyt_c.color("lightorange", heme_mask & (cyt_c.element == "C"))

#----------------------------------------------------------------------#

# Mark the histidine bound to heme as sticks
heme_iron_coord = cyt_c[cyt_c.element == "FE"].coord[0]
adjacency_mask = (struc.distance(cyt_c.coord, heme_iron_coord) < 2.0)
bound_nitrogen_mask = adjacency_mask & (cyt_c.res_name == "HIS")
his_mask = (cyt_c.res_id == cyt_c.res_id[bound_nitrogen_mask])

pymol_cyt_c.show("sticks", his_mask)
pymol_cyt_c.color(
    "darkgreen", his_mask & (cyt_c.element == "C") & (cyt_c.atom_name != "CA"))

#----------------------------------------------------------------------#

# Zoom into binding site
pymol_cyt_c.zoom(heme_mask | his_mask, buffer=1.0)
Ejemplo n.º 12
0
# Geometry measures
# ^^^^^^^^^^^^^^^^^
#
# Let's start with measuring some simple geometric characteristics,
# for example atom distances of CA atoms.

import biotite.structure as struc
import biotite.structure.io as strucio
import biotite.database.rcsb as rcsb
file_path = rcsb.fetch("1l2y", "mmtf", biotite.temp_dir())
stack = strucio.load_structure(file_path)
# Filter only CA atoms
stack = stack[:, stack.atom_name == "CA"]
# Calculate distance between first and second CA in first frame
array = stack[0]
print("Atom to atom:", struc.distance(array[0], array[1]))
# Calculate distance between the first atom
# and all other CA atoms in the array
print("Array to atom:")
array = stack[0]
print(struc.distance(array[0], array))
# Calculate pairwise distances between the CA atoms in the first frame
# and the CA atoms in the second frame
print("Array to array:")
print(struc.distance(stack[0], stack[1]))
# Calculate the distances between all CA atoms in the stack
# and the first CA atom in the first frame
# The resulting array is too large, therefore only the shape is printed
print("Stack to atom:")
print(struc.distance(stack, stack[0, 0]).shape)
# And finally distances between two adjacent CA in the first frame