Beispiel #1
0
    def _execute(self, directory, available_resources):

        yaml_filename = os.path.join(directory, "yank.yaml")

        # Create the yank yaml input file from a dictionary of options.
        with open(yaml_filename, "w") as file:
            yaml.dump(
                self._get_full_input_dictionary(available_resources),
                file,
                sort_keys=False,
            )

        setup_only = self.setup_only

        # Yank is not safe to be called from anything other than the main thread.
        # If the current thread is not detected as the main one, then yank should
        # be spun up in a new process which should itself be safe to run yank in.
        if threading.current_thread() is threading.main_thread():
            logger.info("Launching YANK in the main thread.")
            free_energy, free_energy_uncertainty = self._run_yank(
                directory, available_resources, setup_only)
        else:

            from multiprocessing import Process, Queue

            logger.info("Launching YANK in a new process.")

            # Create a queue to pass the results back to the main process.
            queue = Queue()
            # Create the process within which yank will run.
            process = Process(
                target=BaseYankProtocol._run_yank_as_process,
                args=[queue, directory, available_resources, setup_only],
            )

            # Start the process and gather back the output.
            process.start()
            free_energy, free_energy_uncertainty, exception = queue.get()
            process.join()

            if exception is not None:
                raise exception

        self.estimated_free_energy = openmm_quantity_to_pint(
            free_energy).plus_minus(
                openmm_quantity_to_pint(free_energy_uncertainty))
Beispiel #2
0
def test_openmm_unit_to_pint(openmm_unit, value):

    openmm_quantity = value * openmm_unit
    openmm_raw_value = openmm_quantity.value_in_unit(openmm_unit)

    pint_quantity = openmm_quantity_to_pint(openmm_quantity)
    pint_raw_value = pint_quantity.magnitude

    assert np.allclose(openmm_raw_value, pint_raw_value)
Beispiel #3
0
def test_daltons():

    openmm_quantity = random() * simtk_unit.dalton
    openmm_raw_value = openmm_quantity.value_in_unit(simtk_unit.gram /
                                                     simtk_unit.mole)

    pint_quantity = openmm_quantity_to_pint(openmm_quantity)
    pint_raw_value = pint_quantity.to(unit.gram / unit.mole).magnitude

    assert np.allclose(openmm_raw_value, pint_raw_value)
def get_molecular_weight(smiles):

    from simtk import unit as simtk_unit
    from openforcefield.topology import Molecule

    molecule = Molecule.from_smiles(smiles, allow_undefined_stereo=True)

    molecular_weight = 0.0 * simtk_unit.dalton

    for atom in molecule.atoms:
        molecular_weight += atom.mass

    return openmm_quantity_to_pint(molecular_weight)
Beispiel #5
0
def test_combinatorial_openmm_to_pint():

    all_openmm_units = list(_get_all_openmm_units())

    for i in range(len(all_openmm_units)):

        for j in range(i, len(all_openmm_units)):

            openmm_unit = all_openmm_units[i] * all_openmm_units[j]

            openmm_quantity = random() * openmm_unit
            openmm_raw_value = openmm_quantity.value_in_unit(openmm_unit)

            pint_quantity = openmm_quantity_to_pint(openmm_quantity)
            pint_raw_value = pint_quantity.magnitude

            assert np.isclose(openmm_raw_value, pint_raw_value)
Beispiel #6
0
def test_openmm_unit_conversions(openmm_unit, value):

    openmm_quantity = value * openmm_unit

    openmm_base_quantity = openmm_quantity.in_unit_system(
        simtk_unit.md_unit_system)

    if not isinstance(openmm_base_quantity, simtk_unit.Quantity):
        openmm_base_quantity *= simtk_unit.dimensionless

    pint_base_quantity = openmm_quantity_to_pint(openmm_base_quantity)

    pint_unit = openmm_unit_to_pint(openmm_unit)
    pint_quantity = pint_base_quantity.to(pint_unit)

    pint_raw_value = pint_quantity.magnitude
    openmm_raw_value = openmm_quantity.value_in_unit(openmm_unit)

    assert np.allclose(openmm_raw_value, pint_raw_value)
Beispiel #7
0
    def _execute(self, directory, available_resources):

        import mdtraj
        from openforcefield.topology import Molecule, Topology

        with open(self.force_field_path) as file:
            force_field_source = ForceFieldSource.parse_json(file.read())

        if not isinstance(force_field_source, SmirnoffForceFieldSource):

            raise ValueError(
                "Only SMIRNOFF force fields are supported by this protocol.", )

        # Load in the inputs
        force_field = force_field_source.to_force_field()

        trajectory = mdtraj.load_dcd(self.trajectory_file_path,
                                     self.coordinate_file_path)

        unique_molecules = []

        for component in self.substance.components:

            molecule = Molecule.from_smiles(smiles=component.smiles)
            unique_molecules.append(molecule)

        pdb_file = app.PDBFile(self.coordinate_file_path)
        topology = Topology.from_openmm(pdb_file.topology,
                                        unique_molecules=unique_molecules)

        # Compute the difference between the energies using the reduced force field,
        # and the full force field.
        energy_corrections = None

        if self.use_subset_of_force_field:

            target_system, _ = self._build_reduced_system(
                force_field, topology)

            subset_potentials_path = os.path.join(directory, f"subset.csv")
            subset_potentials = self._evaluate_reduced_potential(
                target_system, trajectory, subset_potentials_path,
                available_resources)

            full_statistics = StatisticsArray.from_pandas_csv(
                self.statistics_path)

            energy_corrections = (
                full_statistics[ObservableType.PotentialEnergy] -
                subset_potentials[ObservableType.PotentialEnergy])

        # Build the slightly perturbed system.
        reverse_system, reverse_parameter_value = self._build_reduced_system(
            force_field, topology, -self.perturbation_scale)

        forward_system, forward_parameter_value = self._build_reduced_system(
            force_field, topology, self.perturbation_scale)

        self.reverse_parameter_value = openmm_quantity_to_pint(
            reverse_parameter_value)
        self.forward_parameter_value = openmm_quantity_to_pint(
            forward_parameter_value)

        # Calculate the reduced potentials.
        self.reverse_potentials_path = os.path.join(directory, "reverse.csv")
        self.forward_potentials_path = os.path.join(directory, "forward.csv")

        self._evaluate_reduced_potential(
            reverse_system,
            trajectory,
            self.reverse_potentials_path,
            available_resources,
            energy_corrections,
        )
        self._evaluate_reduced_potential(
            forward_system,
            trajectory,
            self.forward_potentials_path,
            available_resources,
            energy_corrections,
        )
Beispiel #8
0
def _approximate_box_size_by_density(
    molecules,
    n_copies,
    mass_density,
    box_aspect_ratio,
    box_scaleup_factor=1.1,
):
    """Generate an approximate box size based on the number and molecular
    weight of the molecules present, and a target density for the final
    solvated mixture.

    Parameters
    ----------
    molecules : list of openforcefield.topology.Molecule
        The molecules in the system.
    n_copies : list of int
        The number of copies of each molecule.
    mass_density : pint.Quantity
        The target mass density for final system. It should have units
        compatible with g / mL.
    box_aspect_ratio: List of float
        The aspect ratio of the simulation box, used in conjunction with
        the `mass_density` parameter.
    box_scaleup_factor : float
        The factor by which the estimated box size should be
        increased.

    Returns
    -------
    pint.Quantity
        A list of the three box lengths in units compatible with angstroms.
    """

    volume = 0.0 * unit.angstrom**3

    for (molecule, number) in zip(molecules, n_copies):

        molecule_mass = reduce((lambda x, y: x + y),
                               [atom.mass for atom in molecule.atoms])
        molecule_mass = openmm_quantity_to_pint(
            molecule_mass) / unit.avogadro_constant

        molecule_volume = molecule_mass / mass_density

        volume += molecule_volume * number

    box_length = volume**(1.0 / 3.0) * box_scaleup_factor
    box_length_angstrom = box_length.to(unit.angstrom).magnitude

    aspect_ratio_normalizer = (box_aspect_ratio[0] * box_aspect_ratio[1] *
                               box_aspect_ratio[2])**(1.0 / 3.0)

    box_size = [
        box_length_angstrom * box_aspect_ratio[0],
        box_length_angstrom * box_aspect_ratio[1],
        box_length_angstrom * box_aspect_ratio[2],
    ] * unit.angstrom

    box_size /= aspect_ratio_normalizer

    return box_size