def _execute(self, directory, available_resources):

        from paprika.evaluator import Setup

        # Construct the restraints to keep the host in place and
        # with an open cavity.
        static_restraints = Setup.build_static_restraints(
            self.host_coordinate_path,
            None,
            None,
            len(self.release_lambdas),
            self.restraint_schemas.get("static", []),
        )
        conformational_restraints = Setup.build_conformational_restraints(
            self.host_coordinate_path,
            None,
            None,
            self.release_lambdas,
            self.restraint_schemas.get("conformational", []),
        )

        self._save_restraints(
            directory,
            static_restraints,
            conformational_restraints,
        )
def complex_file_path(tmp_path):

    import parmed.geometry
    from paprika.evaluator import Setup

    complex_path = get_data_filename(
        os.path.join("test", "molecules", "methanol_methane.pdb")
    )

    # noinspection PyTypeChecker
    structure: parmed.Structure = parmed.load_file(complex_path, structure=True)
    # noinspection PyTypeChecker
    center_of_mass = parmed.geometry.center_of_mass(
        structure.coordinates, masses=numpy.ones(len(structure.coordinates))
    )

    Setup.add_dummy_atoms_to_structure(
        structure,
        [
            numpy.array([0.0, 0.0, 10.0]),
            numpy.array([0.0, 0.0, 20.0]),
            numpy.array([0.0, 5.0, 25.0]),
        ],
        center_of_mass,
    )

    complex_path = os.path.join(tmp_path, "complex.pdb")
    structure.save(complex_path)

    return complex_path
    def _execute(self, directory, available_resources):

        from paprika.evaluator import Setup

        # Construct the restraints to keep the host in place and
        # with an open cavity.
        static_restraints = Setup.build_static_restraints(
            self.complex_coordinate_path,
            len(self.attach_lambdas),
            None,
            None,
            self.restraint_schemas.get("static", []),
        )
        conformational_restraints = Setup.build_conformational_restraints(
            self.complex_coordinate_path,
            self.attach_lambdas,
            None,
            None,
            self.restraint_schemas.get("conformational", []),
        )

        # Construct the restraints to keep the guest at the correct
        # distance and orientation relative to the host.
        symmetry_restraints = Setup.build_symmetry_restraints(
            self.complex_coordinate_path,
            len(self.attach_lambdas),
            self.restraint_schemas.get("symmetry", []),
        )
        wall_restraints = Setup.build_wall_restraints(
            self.complex_coordinate_path,
            len(self.attach_lambdas),
            self.restraint_schemas.get("wall", []),
        )
        guest_restraints = Setup.build_guest_restraints(
            self.complex_coordinate_path,
            self.attach_lambdas,
            None,
            self.restraint_schemas.get("guest", []),
        )

        self._save_restraints(
            directory,
            static_restraints,
            conformational_restraints,
            symmetry_restraints,
            wall_restraints,
            guest_restraints,
        )
    def _execute(self, directory, available_resources):

        import mdtraj
        from paprika.evaluator import Setup
        from simtk.openmm import app

        mdtraj_trajectory = mdtraj.load_pdb(self.complex_file_path)

        atom_indices_by_role = _atom_indices_by_role(
            self.substance, self.complex_file_path
        )
        host_atom_indices = atom_indices_by_role[Component.Role.Receptor]

        host_trajectory = mdtraj_trajectory.atom_slice(host_atom_indices)

        host_file_path = os.path.join(directory, "host_input.pdb")
        host_trajectory.save(host_file_path)

        host_structure = Setup.prepare_host_structure(host_file_path)

        self.output_coordinate_path = os.path.join(directory, "output.pdb")

        with open(self.output_coordinate_path, "w") as file:
            app.PDBFile.writeFile(
                host_structure.topology, host_structure.positions, file, True
            )
    def _execute(self, directory, available_resources):

        from paprika.evaluator import Setup
        from simtk.openmm import app

        atom_indices_by_role = _atom_indices_by_role(
            self.substance, self.complex_file_path
        )

        guest_atom_indices = atom_indices_by_role[Component.Role.Ligand]

        host_structure = Setup.prepare_complex_structure(
            self.complex_file_path,
            guest_atom_indices,
            self.guest_orientation_mask,
            self.pull_distance.to(unit.angstrom).magnitude,
            self.pull_window_index,
            self.n_pull_windows,
        )

        self.output_coordinate_path = os.path.join(directory, "output.pdb")

        with open(self.output_coordinate_path, "w") as file:
            app.PDBFile.writeFile(
                host_structure.topology, host_structure.positions, file, True
            )
    def _execute(self, directory, available_resources):

        from paprika.evaluator import Setup

        # Construct the restraints to keep the host in place and
        # with an open cavity.
        static_restraints = Setup.build_static_restraints(
            self.complex_coordinate_path,
            len(self.attach_lambdas),
            self.n_pull_windows,
            None,
            self.restraint_schemas.get("static", []),
        )
        conformational_restraints = Setup.build_conformational_restraints(
            self.complex_coordinate_path,
            self.attach_lambdas,
            self.n_pull_windows,
            None,
            self.restraint_schemas.get("conformational", []),
        )

        # Construct the restraints to keep the guest at the correct
        # distance to the host.
        guest_restraints = Setup.build_guest_restraints(
            self.complex_coordinate_path,
            self.attach_lambdas,
            self.n_pull_windows,
            self.restraint_schemas.get("guest", []),
        )

        # Remove the attach phases from the restraints as these restraints are
        # only being used for the pull phase.
        for restraint in (
            static_restraints + conformational_restraints + guest_restraints
        ):

            for key in restraint.phase["attach"]:
                restraint.phase["attach"][key] = None

        self._save_restraints(
            directory,
            static_restraints,
            conformational_restraints,
            None,
            None,
            guest_restraints,
        )
    def _execute(self, directory, available_resources):

        import parmed.geometry
        from paprika.evaluator import Setup
        from simtk.openmm import NonbondedForce, XmlSerializer, app

        # Extract the host atoms to determine the offset of the dummy atoms.
        # noinspection PyTypeChecker
        input_structure: parmed.Structure = parmed.load_file(
            self.input_coordinate_path, structure=True
        )

        # Add the dummy atoms to the structure.
        offset = self.offset.to(unit.angstrom).magnitude

        Setup.add_dummy_atoms_to_structure(
            input_structure,
            [
                numpy.array([0, 0, -offset]),
                numpy.array([0, 0, -3.0 - offset]),
                numpy.array([0, 2.2, -5.2 - offset]),
            ],
            numpy.zeros(3),
        )

        # Shift the structure to avoid issues with the PBC
        input_structure.coordinates += numpy.array(
            [
                input_structure.box[0] * 0.5,
                input_structure.box[1] * 0.5,
                -input_structure.coordinates[-1, 2] + 1.0,
            ]
        )

        # Save the final coordinates.
        self.output_coordinate_path = os.path.join(directory, "output.pdb")

        with open(self.output_coordinate_path, "w") as file:
            app.PDBFile.writeFile(
                input_structure.topology, input_structure.positions, file, True
            )

        # Add the dummy atoms to the system.
        system = self.input_system.system

        for _ in range(3):
            system.addParticle(mass=207)

        for force_index in range(system.getNumForces()):

            force = system.getForce(force_index)

            if not isinstance(force, NonbondedForce):
                continue

            force.addParticle(0.0, 1.0, 0.0)
            force.addParticle(0.0, 1.0, 0.0)
            force.addParticle(0.0, 1.0, 0.0)

        output_system_path = os.path.join(directory, "output.xml")

        with open(output_system_path, "w") as file:
            file.write(XmlSerializer.serialize(system))

        self.output_system = ParameterizedSystem(
            self.input_system.substance,
            self.input_system.force_field,
            self.output_coordinate_path,
            output_system_path,
        )
def test_evaluator_setup_structure(clean_files):
    temporary_directory = os.path.join(os.path.dirname(__file__), "tmp")

    G1 = ":BUT@C"
    G2 = ":BUT@C3"

    # Test prepare_complex_structure
    host_guest_pdb = os.path.join(os.path.dirname(__file__),
                                  "../data/cb6-but/vac.pdb")
    guest_atom_indices = []
    structure = pmd.load_file(host_guest_pdb, structure=True)
    for atom in structure.topology.atoms():
        if atom.residue.name == "BUT":
            guest_atom_indices.append(atom.index)

    host_guest_structure_initial = Setup.prepare_complex_structure(
        host_guest_pdb,
        guest_atom_indices,
        f"{G1} {G2}",
        24.0,
        0,
        46,
    )

    assert all(
        host_guest_structure_initial[G1].coordinates[0] == [0.0, 0.0, 0.0])

    host_guest_structure_final = Setup.prepare_complex_structure(
        host_guest_pdb,
        guest_atom_indices,
        f"{G1} {G2}",
        24.0,
        45,
        46,
    )
    assert all(
        host_guest_structure_final[G1].coordinates[0] == [0.0, 0.0, 24.0])

    cG1 = host_guest_structure_final[G1].coordinates[0]
    cG2 = host_guest_structure_final[G2].coordinates[0]
    vec = cG2 - cG1
    axis = np.array([0, 0, 1])
    theta = np.arccos(
        np.dot(vec, axis) / (np.linalg.norm(vec) * np.linalg.norm(axis)))
    assert theta == 0.0

    # Test prepare_host_structure
    structure = pmd.load_file(host_guest_pdb, structure=True)
    structure[":CB6"].save(os.path.join(temporary_directory, "cb6.pdb"))
    host_pdb = os.path.join(temporary_directory, "cb6.pdb")
    host_atom_indices = []
    for atom in structure.topology.atoms():
        if atom.residue.name == "CB6":
            host_atom_indices.append(atom.index)

    host_structure = Setup.prepare_host_structure(
        host_pdb,
        host_atom_indices,
    )
    center_of_mass = pmd.geometry.center_of_mass(
        host_structure.coordinates,
        masses=np.ones(len(host_structure.coordinates)))
    assert pytest.approx(center_of_mass[0], abs=1e-3) == 0.0
    assert pytest.approx(center_of_mass[1], abs=1e-3) == 0.0
    assert pytest.approx(center_of_mass[2], abs=1e-3) == 0.0

    inertia_tensor = np.dot(host_structure.coordinates.transpose(),
                            host_structure.coordinates)
    eig_val, eig_vec = np.linalg.eig(inertia_tensor)
    assert pytest.approx(eig_vec[0, -1], abs=1e-3) == 0.0
    assert pytest.approx(eig_vec[1, -1], abs=1e-3) == 0.0
    assert pytest.approx(eig_vec[2, -1], abs=1e-3) == 1.0

    # Test add dummy
    Setup.add_dummy_atoms_to_structure(
        host_structure,
        [
            np.array([0, 0, 0]),
            np.array([0, 0, -3.0]),
            np.array([0, 2.2, -5.2]),
        ],
        np.zeros(3),
    )
    dummy_atoms = []
    for atom in host_structure.topology.atoms():
        if atom.name == "DUM":
            dummy_atoms.append(atom)

    assert len(dummy_atoms) == 3
    assert pytest.approx(host_structure[":DM1"].coordinates[0][2],
                         abs=1e-3) == 0.0
    assert pytest.approx(host_structure[":DM2"].coordinates[0][2],
                         abs=1e-3) == -3.0
    assert pytest.approx(host_structure[":DM3"].coordinates[0][1],
                         abs=1e-3) == 2.2
    assert pytest.approx(host_structure[":DM3"].coordinates[0][2],
                         abs=1e-3) == -5.2
def test_evaluator_analyze(clean_files):
    input_pdb = os.path.join(os.path.dirname(__file__),
                             "../data/cb6-but/vac.pdb")
    structure = pmd.load_file(input_pdb, structure=True)

    guest_atom_indices = []
    for atom in structure.topology.atoms():
        if atom.residue.name == "BUT":
            guest_atom_indices.append(atom.index)

    host_guest_structure = Setup.prepare_complex_structure(
        input_pdb,
        guest_atom_indices,
        ":BUT@C :BUT@C3",
        24.0,
        0,
        46,
    )
    Setup.add_dummy_atoms_to_structure(
        host_guest_structure,
        [
            np.array([0, 0, 0]),
            np.array([0, 0, -3.0]),
            np.array([0, 2.2, -5.2]),
        ],
        np.zeros(3),
    )

    # Distance restraint
    rest1 = DAT_restraint()
    rest1.continuous_apr = True
    rest1.amber_index = True
    rest1.topology = host_guest_structure
    rest1.mask1 = ":DM1"
    rest1.mask2 = ":BUT@C"
    rest1.attach["target"] = 6.0
    rest1.attach["fraction_list"] = [0.00, 0.04, 0.181, 0.496, 1.000]
    rest1.attach["fc_final"] = 5.0
    rest1.pull["fc"] = rest1.attach["fc_final"]
    rest1.pull["target_initial"] = rest1.attach["target"]
    rest1.pull["target_final"] = 24.0
    rest1.pull["num_windows"] = 19
    rest1.initialize()

    # Angle 1 restraint
    rest2 = DAT_restraint()
    rest2.continuous_apr = True
    rest2.amber_index = True
    rest2.topology = input_pdb
    rest2.mask1 = ":DM2"
    rest2.mask2 = ":DM1"
    rest2.mask3 = ":BUT@C"
    rest2.attach["target"] = 180.0
    rest2.attach["fraction_list"] = [0.00, 0.04, 0.181, 0.496, 1.000]
    rest2.attach["fc_final"] = 100.0
    rest2.pull["fc"] = rest2.attach["fc_final"]
    rest2.pull["target_initial"] = rest2.attach["target"]
    rest2.pull["target_final"] = rest2.attach["target"]
    rest2.pull["num_windows"] = 19
    rest2.initialize()

    # Angle 2
    rest3 = DAT_restraint()
    rest3.continuous_apr = True
    rest3.amber_index = True
    rest3.topology = input_pdb
    rest3.mask1 = ":DM1"
    rest3.mask2 = ":BUT@C"
    rest3.mask3 = ":BUT@C3"
    rest3.attach["target"] = 180.0
    rest3.attach["fraction_list"] = [0.00, 0.04, 0.181, 0.496, 1.000]
    rest3.attach["fc_final"] = 100.0
    rest3.pull["fc"] = rest2.attach["fc_final"]
    rest3.pull["target_initial"] = rest2.attach["target"]
    rest3.pull["target_final"] = rest2.attach["target"]
    rest3.pull["num_windows"] = 19
    rest3.initialize()

    temperature = 298.15
    guest_restraints = [rest1, rest2, rest3]
    ref_state_work = Analyze.compute_ref_state_work(temperature,
                                                    guest_restraints)
    assert pytest.approx(ref_state_work, abs=1e-3) == -7.14151

    fe_sym = Analyze.symmetry_correction(n_microstates=1, temperature=298.15)
    assert fe_sym == 0.0
    fe_sym = Analyze.symmetry_correction(n_microstates=2, temperature=298.15)
    assert pytest.approx(fe_sym, abs=1e-3) == -0.410679