예제 #1
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
예제 #2
0
def test_get_molecule_indices(array, as_stack, as_bonds):
    """
    Multiple tests to :func:`get_molecule_indices()` on a
    :class:`AtomArray` of random molecules.
    """
    if as_stack:
        array = struc.stack([array])

    if as_bonds:
        test_indices = struc.get_molecule_indices(array.bonds)
    else:
        test_indices = struc.get_molecule_indices(array)

    seen_atoms = 0
    for indices in test_indices:
        molecule = array[..., indices]
        # Assert that all residue IDs in the molecule are equal
        # -> all atoms from the same molecule
        assert (molecule.res_id == molecule.res_id[0]).all()
        # Assert that no atom is missing from the molecule
        assert molecule.array_length() \
            == info.residue(molecule.res_name[0]).array_length()
        seen_atoms += molecule.array_length()
    # Assert that all molecules are fond
    assert seen_atoms == array.array_length()
예제 #3
0
def test_molecule_iter(array, as_stack):
    """
    Test whether :func:`molecule_iter()` gives the same molecules as
    pointed by :func:`get_molecule_indices()`.
    """
    if as_stack:
        array = struc.stack([array])

    ref_indices = struc.get_molecule_indices(array)
    test_iterator = struc.molecule_iter(array)

    for i, molecule in enumerate(test_iterator):
        assert molecule == array[..., ref_indices[i]]
예제 #4
0
def test_remove_pbc_selections(multi_model):
    """
    This test makes no assertions, it only test whether an exception
    occurs, when the `selection` parameter is given in `remove_pbc()`.
    """
    array = load_structure(join(data_dir("structure"), "3o5r.mmtf"))
    if multi_model:
        array = struc.stack([array, array])

    struc.remove_pbc(array)
    struc.remove_pbc(array, array.chain_id[0])
    struc.remove_pbc(array, struc.filter_amino_acids(array))
    struc.remove_pbc(
        array, [struc.filter_amino_acids(array), (array.res_name == "FK5")])
    # Expect error when selectinf an atom multiple times
    with pytest.raises(ValueError):
        struc.remove_pbc(
            array,
            [struc.filter_amino_acids(array), (array.atom_name == "CA")])
예제 #5
0
def test_get_molecule_masks(array, as_stack, as_bonds):
    """
    Test whether the masks returned by :func:`get_molecule_masks()`
    point to the same atoms as the indices returned by
    :func:`get_molecule_indices()`.
    """
    if as_stack:
        array = struc.stack([array])

    if as_bonds:
        ref_indices = struc.get_molecule_indices(array.bonds)
        test_masks = struc.get_molecule_masks(array.bonds)
    else:
        ref_indices = struc.get_molecule_indices(array)
        test_masks = struc.get_molecule_masks(array)

    for i in range(len(test_masks)):
        # Assert that the mask is 'True' for all indices
        # and that these 'True' values are the only ones in the mask
        assert (test_masks[i, ref_indices[i]] == True).all()
        assert np.count_nonzero(test_masks[i]) == len(ref_indices[i])
예제 #6
0
def test_read_iter_structure(format, start, stop, step):
    """
    Compare aggregated yields of :func:`read_iter_structure()` with the
    return value of :func:`get_structure()` from a corresponding
    :class:`TrajectoryFile` object.
    """
    if format == "netcdf" and step is not None:
        # Currently, there is an inconsistency in in MDTraj's
        # NetCDFTrajectoryFile class:
        # In this class the number of frames in the output arrays
        # is dependent on the 'stride' parameter
        return

    template = strucio.load_structure(join(data_dir("structure"), "1l2y.mmtf"))

    if format == "trr":
        traj_file_cls = trr.TRRFile
    if format == "xtc":
        traj_file_cls = xtc.XTCFile
    if format == "tng":
        traj_file_cls = tng.TNGFile
    if format == "dcd":
        traj_file_cls = dcd.DCDFile
    if format == "netcdf":
        traj_file_cls = netcdf.NetCDFFile
    file_name = join(data_dir("structure"), f"1l2y.{format}")

    traj_file = traj_file_cls.read(file_name, start, stop, step)
    ref_traj = traj_file.get_structure(template)

    test_traj = struc.stack([
        frame for frame in traj_file_cls.read_iter_structure(
            file_name, template, start, stop, step)
    ])

    assert test_traj == ref_traj
예제 #7
0
def stack(array):
    return struc.stack([array, array.copy(), array.copy()])
예제 #8
0
# (multiple models in NMR structures, MD trajectories).
# For the cases :class:`AtomArrayStack` objects are used, which
# represent a list of atom arrays.
# Since the atoms are the same for each frame, but only the coordinates
# change, the annotation arrays in stacks are still the same length *n*
# :class:`ndarray` objects as in atom arrays.
# However, a stack stores the coordinates in a *(m,n,3)*-shaped
# :class:`ndarray`, where *m* is the number of frames.
# A stack is constructed with :func:`stack()` analogous to the code
# snipped above.
# It is crucial that all arrays that should be stacked
# have the same annotation arrays, otherwise an exception is raised.
# For simplicity reasons, we create a stack containing two identical
# models, derived from the previous example.

stack = struc.stack([array, array.copy()])
print(stack)

########################################################################
# Loading structures from file
# ----------------------------
#
# Usually structures are not built from scratch in *Biotite*,
# but they are read from a file.
# Probably the most popular strcuture file format is the *PDB* format.
# For our purpose, we will work on a protein structure as small as
# possible, namely the miniprotein *TC5b* (PDB: ``1L2Y```).
# The structure of this 20-residue protein (304 atoms) has been
# elucidated via NMR.
# Thus, the corresponding PDB file consists of multiple (namely 38)
# models, each showing another conformation.