예제 #1
0
def test_extract_dummy():
    cb6 = pmd.load_file(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/vac.pdb")
    )
    aligned_cb6 = zalign(cb6, ":CB6", ":BUT")
    aligned_cb6 = add_dummy(aligned_cb6, residue_name="DM1", z=-6.0)
    aligned_cb6 = add_dummy(aligned_cb6, residue_name="DM2", z=-9.0)
    aligned_cb6 = add_dummy(aligned_cb6, residue_name="DM3", z=-11.2, y=2.2)

    dm_index = []
    for atom in aligned_cb6.topology.atoms():
        if atom.residue.name in ["DM1", "DM2", "DM3"]:
            dm_index.append(atom.index)

    assert len(dm_index) != 0

    dummy_dict = extract_dummy_atoms(aligned_cb6, serial=False)

    assert all(dummy_dict["DM1"]["pos"] == [0.0, 0.0, -6.0])
    assert all(dummy_dict["DM2"]["pos"] == [0.0, 0.0, -9.0])
    assert all(dummy_dict["DM3"]["pos"] == [0.0, 2.2, -11.2])

    assert dummy_dict["DM1"]["mass"] == 208.0
    assert dummy_dict["DM2"]["mass"] == 208.0
    assert dummy_dict["DM3"]["mass"] == 208.0

    assert dummy_dict["DM1"]["idx"] == dm_index[0]
    assert dummy_dict["DM2"]["idx"] == dm_index[1]
    assert dummy_dict["DM3"]["idx"] == dm_index[2]
예제 #2
0
def test_center_mask():
    """ Test that the first mask is centered """
    cb6 = pmd.load_file(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/vac.pdb"))
    aligned_cb6 = zalign(cb6, ":CB6", ":BUT")
    test_coordinates = check_coordinates(aligned_cb6, ":CB6")
    assert np.allclose(test_coordinates, np.zeros(3))
예제 #3
0
def test_alignment_after_offset():
    """ Test that molecule is properly aligned after random offset. """
    cb6 = pmd.load_file(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/vac.pdb"))
    random_coordinates = np.random.randint(10) * np.random.rand(1, 3)
    cb6_offset = offset_structure(cb6, random_coordinates)
    aligned_cb6 = zalign(cb6_offset, ":CB6", ":BUT")
    test_coordinates = check_coordinates(aligned_cb6, ":CB6")
    assert np.allclose(test_coordinates, np.zeros(3))
예제 #4
0
def test_theta_after_alignment():
    """ Test that molecule is properly aligned after random offset. """
    cb6 = pmd.load_file(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/vac.pdb"))
    aligned_cb6 = zalign(cb6, ":CB6", ":BUT")
    assert get_theta(aligned_cb6, ":CB6", ":BUT", axis="z") == 0
    assert (pytest.approx(get_theta(aligned_cb6, ":CB6", ":BUT", axis="x"),
                          abs=1e-3) == 1.5708)
    assert (pytest.approx(get_theta(aligned_cb6, ":CB6", ":BUT", axis="y"),
                          abs=1e-3) == 1.5708)
예제 #5
0
def test_alignment_workflow(clean_files):
    """ Test that we can solvate CB6-BUT after alignment. """
    cb6 = pmd.load_file(
        os.path.join(
            os.path.dirname(__file__), "../data/cb6-but/cb6-but-notcentered.pdb"
        )
    )
    zalign(cb6, ":CB6", ":BUT", save=True, filename="./tmp/tmp.pdb")
    waters = np.random.randint(1000, 10000)
    sys = TLeap()
    sys.template_file = os.path.join(
        os.path.dirname(__file__), "../data/cb6-but/tleap_solvate.in"
    )
    sys.output_path = "tmp"
    sys.loadpdb_file = "tmp.pdb"
    sys.target_waters = waters
    sys.output_prefix = "solvate"
    sys.build()
    logger.debug("Trying {} waters after alignment...".format(waters))
    grepped_waters = sp.check_output(
        ["grep -oh 'WAT' ./tmp/solvate.prmtop | wc -w"], shell=True
    )
    assert int(grepped_waters) == waters
예제 #6
0
    def prepare_host_structure(
        cls, coordinate_path: str, host_atom_indices: Optional[List[int]] = None
    ) -> pmd.Structure:
        """Prepares the coordinates of a host molecule ready for the release phase of
        an APR calculation.
        This currently involves aligning the cavity of the host along the z-axis, and
        positioning the host so that its center of geometry at (0, 0, 0).

        Notes
        -----
        The hosts cavity axis is for now determined as the vector orthogonal to the
        two largest principal components of the host.

        Parameters
        ----------
        coordinate_path
            The path to the coordinate file which contains the host molecule.
        host_atom_indices
            The (0-based) indices of the host atoms in the coordinate file if the
            file. This may be used if the coordinate file contains more than a single
            molecule.

        Returns
        -------
            A ParmEd structure which contains only the aligned and centered host.
            If ``host_atom_indices`` are provided, the structure will contain only
            the referenced host atoms.
        """

        # noinspection PyTypeChecker
        structure = pmd.load_file(coordinate_path, structure=True)

        # Extract the host from the full structure.
        if not host_atom_indices:
            host_atom_indices = range(len(structure.atoms))

        host_structure = structure[
            "@" + ",".join(map(lambda x: str(x + 1), host_atom_indices))
        ]

        # noinspection PyTypeChecker
        center_of_mass: np.ndarray = pmd.geometry.center_of_mass(
            host_structure.coordinates, masses=np.ones(len(host_structure.coordinates))
        )

        # Remove the COM from the host coordinates to make alignment easier.
        structure.coordinates -= center_of_mass
        host_structure.coordinates -= center_of_mass

        # Find the principal components of the host, take the two largest, and find
        # the vector orthogonal to that. Use that vector to align with the z-axis.
        # This may not generalize to non-radially-symmetric host molecules.
        inertia_tensor = np.dot(
            host_structure.coordinates.transpose(), host_structure.coordinates
        )

        eigenvalues, eigenvectors = np.linalg.eig(inertia_tensor)
        order = np.argsort(eigenvalues)

        _, axis_2, axis_1 = eigenvectors[:, order].transpose()

        cavity_axis = np.cross(axis_1, axis_2)

        # Add dummy atoms which will be used to align the structure.
        cls.add_dummy_atoms_to_structure(structure, [np.array([0, 0, 0]), cavity_axis])

        # Give atoms uniform mass so that the align code uses the center
        # of geometry rather than the center of mass.
        for atom in structure.atoms:
            atom.mass = 1.0

        aligned_structure = align.zalign(structure, ":DM1", ":DM2")

        # Return a copy of the original structure where things like the masses
        # have not been changed and dummy atoms not added.

        # noinspection PyTypeChecker
        structure: pmd.Structure = pmd.load_file(coordinate_path, structure=True)
        structure.coordinates = aligned_structure["!:DM1&!:DM2"].coordinates

        return structure
예제 #7
0
    def prepare_complex_structure(
        cls,
        coordinate_path: str,
        guest_atom_indices: List[int],
        guest_orientation_mask: str,
        pull_distance: float,
        pull_window_index: int,
        n_pull_windows: int,
    ) -> pmd.Structure:
        """Prepares the coordinates of a host molecule ready for the pull (+ attach)
        phase of an APR calculation.

        This currently involves aligning the complex so that the guest molecule (or
        rather, the guest atoms specified by ``guest_orientation_mask``) is aligned
        with the z-axis, and the first atom specified by ``guest_orientation_mask`` is
        positioned at (0, 0, 0).

        Parameters
        ----------
        coordinate_path
            The path to the coordinate file which contains the guest molecule
            bound to the host.
        guest_atom_indices
            The (0-based) indices of the atoms in the coordinate file which
            correspond to the guest molecule.
        guest_orientation_mask
            The string mask which describes which guest atoms will be restrained to
            keep the molecule aligned to the z-axis and at a specific distance from
            the host. This should be of the form 'X Y' where X Y are ParmEd selectors
            for the two guest atoms to restrain relative to the dummy atoms.
        pull_distance
            The total distance that the guest will be pulled along the z-axis during
            the pull phase in units of Angstroms.
        pull_window_index
            The index of the window to prepare coordinates for. This determines the
            distance to place the guest from the host in the returned structure. An
            index of zero corresponds to the guest in its initial position, while an
            ``index = n_pull_windows - `` corresponds to the guest positioned
            a distance of ``pull_distance`` away from the host.
        n_pull_windows
            The total number of pull windows being used in the calculation. This
            will determine the distance to move the guest at each window.

        Returns
        -------
            A ParmEd structure which contains the aligned and positioned host and
            guest molecules.
        """

        # Align the host-guest complex so the first guest atom is at (0, 0, 0) and the
        # second guest atom lies along the positive z-axis.
        # noinspection PyTypeChecker
        structure: pmd.Structure = pmd.load_file(coordinate_path, structure=True)

        (
            guest_orientation_mask_0,
            guest_orientation_mask_1,
        ) = guest_orientation_mask.split(" ")

        aligned_structure = align.zalign(
            structure, guest_orientation_mask_0, guest_orientation_mask_1
        )

        target_distance = np.linspace(0.0, pull_distance, n_pull_windows)[
            pull_window_index
        ]
        target_difference = target_distance

        for guest_index in guest_atom_indices:
            aligned_structure.atoms[guest_index].xz += target_difference

        return aligned_structure
예제 #8
0
def test_add_dummy(clean_files):
    """ Test that dummy atoms get added correctly """
    temporary_directory = os.path.join(os.path.dirname(__file__), "tmp")
    host_guest = pmd.load_file(
        os.path.join(
            os.path.dirname(__file__), "../data/cb6-but/cb6-but-notcentered.pdb"
        ),
        structure=True,
    )
    host_guest = zalign(host_guest, ":BUT@C", ":BUT@C3", save=False)
    host_guest = add_dummy(host_guest, residue_name="DM1", z=-11.000, y=2.000, x=-1.500)

    host_guest.write_pdb(
        os.path.join(temporary_directory, "cb6-but-dum.pdb"), renumber=False
    )
    with open(os.path.join(temporary_directory, "cb6-but-dum.pdb"), "r") as f:
        lines = f.readlines()
        test_line1 = lines[123].rstrip()
        test_line2 = lines[124].rstrip()
    ref_line1 = "TER     123      BUT     2"
    ref_line2 = (
        "HETATM  123 DUM  DM1     3      -1.500   2.000 -11.000  0.00  0.00          PB"
    )
    assert ref_line1 == test_line1
    assert ref_line2 == test_line2

    write_dummy_frcmod(path=temporary_directory)
    write_dummy_mol2(path=temporary_directory, filename="dm1.mol2", residue_name="DM1")
    sys = TLeap()
    cb6_frcmod = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/cb6.frcmod")
    )
    cb6_mol2 = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/cb6.mol2")
    )
    but_frcmod = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/but.frcmod")
    )
    but_mol2 = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/but.mol2")
    )

    sys.template_lines = [
        "source leaprc.gaff",
        f"loadamberparams {cb6_frcmod}",
        f"CB6 = loadmol2 {cb6_mol2}",
        f"loadamberparams {but_frcmod}",
        f"BUT = loadmol2 {but_mol2}",
        "loadamberparams dummy.frcmod",
        "DM1 = loadmol2 dm1.mol2",
        "model = loadpdb cb6-but-dum.pdb",
    ]
    sys.output_path = temporary_directory
    sys.output_prefix = "cb6-but-dum"
    sys.pbc_type = None
    sys.neutralize = False
    sys.build()
    with open(
        os.path.join(os.path.dirname(__file__), "../data/cb6-but/REF_cb6-but-dum.rst7"),
        "r",
    ) as f:
        contents = f.read()
        reference = [float(i) for i in contents.split()[2:]]

    with open(os.path.join(temporary_directory, "cb6-but-dum.rst7"), "r") as f:
        contents = f.read()
        new = [float(i) for i in contents.split()[2:]]
    assert np.allclose(reference, new)