예제 #1
0
def test_packmol_failed():

    from openff.toolkit.topology import Molecule

    molecules = [Molecule.from_smiles("O")]

    with pytest.raises(PackmolRuntimeException):
        packmol.pack_box(molecules, [10], box_size=([0.1] * 3) * unit.angstrom)
예제 #2
0
def test_packmol_bad_input():

    from openff.toolkit.topology import Molecule

    molecules = [Molecule.from_smiles("O")]

    with pytest.raises(ValueError):
        packmol.pack_box(molecules, [10, 20],
                         box_size=([20] * 3) * unit.angstrom)
예제 #3
0
def test_packmol_ions():

    from openff.toolkit.topology import Molecule

    molecules = [
        Molecule.from_smiles("[Na+]"),
        Molecule.from_smiles("[Cl-]"),
        Molecule.from_smiles("[K+]"),
    ]

    trajectory, _ = packmol.pack_box(molecules, [1, 1, 1],
                                     box_size=([20] * 3) * unit.angstrom)

    assert trajectory is not None

    assert trajectory.n_chains == 3
    assert trajectory.n_residues == 3
    assert trajectory.n_atoms == 3
    assert trajectory.topology.n_bonds == 0

    assert trajectory.top.residue(0).name == "Na+"
    assert trajectory.top.residue(1).name == "Cl-"
    assert trajectory.top.residue(2).name == "K+"

    assert trajectory.top.atom(0).name == "Na+"
    assert trajectory.top.atom(1).name == "Cl-"
    assert trajectory.top.atom(2).name == "K+"
예제 #4
0
    def _execute(self, directory, available_resources):

        molecules, number_of_molecules, exception = self._build_molecule_arrays()

        packmol_directory = path.join(directory, "packmol_files")

        # Create packed box
        trajectory, residue_names = packmol.pack_box(
            molecules=molecules,
            number_of_copies=number_of_molecules,
            structure_to_solvate=self.solute_coordinate_file,
            center_solute=self.center_solute_in_box,
            mass_density=self.mass_density,
            box_aspect_ratio=self.box_aspect_ratio,
            tolerance=self.tolerance,
            verbose=self.verbose_packmol,
            working_directory=packmol_directory,
            retain_working_files=self.retain_packmol_files,
        )

        if trajectory is None:
            raise RuntimeError("Packmol failed to complete.")

        self.assigned_residue_names = dict()

        for component, residue_name in zip(self.substance, residue_names):
            self.assigned_residue_names[component.identifier] = residue_name

        self._save_results(directory, trajectory)
예제 #5
0
def test_packmol_paracetamol():

    from openff.toolkit.topology import Molecule

    # Test something a bit more tricky than water
    molecules = [Molecule.from_smiles("CC(=O)NC1=CC=C(C=C1)O")]

    trajectory, _ = packmol.pack_box(molecules, [1],
                                     box_size=([20] * 3) * unit.angstrom)

    assert trajectory is not None

    assert trajectory.n_chains == 1
    assert trajectory.n_residues == 1
    assert trajectory.n_atoms == 20
    assert trajectory.topology.n_bonds == 20
예제 #6
0
def test_amino_acids():

    amino_residues = {
        "C[C@H](N)C(=O)O": "ALA",
        # Undefined stereochemistry error.
        # "N=C(N)NCCC[C@H](N)C(=O)O": "ARG",
        "NC(=O)C[C@H](N)C(=O)O": "ASN",
        "N[C@@H](CC(=O)O)C(=O)O": "ASP",
        "N[C@@H](CS)C(=O)O": "CYS",
        "N[C@@H](CCC(=O)O)C(=O)O": "GLU",
        "NC(=O)CC[C@H](N)C(=O)O": "GLN",
        "NCC(=O)O": "GLY",
        "N[C@@H](Cc1c[nH]cn1)C(=O)O": "HIS",
        "CC[C@H](C)[C@H](N)C(=O)O": "ILE",
        "CC(C)C[C@H](N)C(=O)O": "LEU",
        "NCCCC[C@H](N)C(=O)O": "LYS",
        "CSCC[C@H](N)C(=O)O": "MET",
        "N[C@@H](Cc1ccccc1)C(=O)O": "PHE",
        "O=C(O)[C@@H]1CCCN1": "PRO",
        "N[C@@H](CO)C(=O)O": "SER",
        "C[C@@H](O)[C@H](N)C(=O)O": "THR",
        "N[C@@H](Cc1c[nH]c2ccccc12)C(=O)O": "TRP",
        "N[C@@H](Cc1ccc(O)cc1)C(=O)O": "TYR",
        "CC(C)[C@H](N)C(=O)O": "VAL",
    }

    smiles = [*amino_residues]

    from openff.toolkit.topology import Molecule

    molecules = [Molecule.from_smiles(x) for x in smiles]
    counts = [1] * len(smiles)

    trajectory, _ = packmol.pack_box(molecules,
                                     counts,
                                     box_size=([1000] * 3) * unit.angstrom)

    assert trajectory is not None

    assert trajectory.n_chains == len(smiles)
    assert trajectory.n_residues == len(smiles)

    for index, smiles in enumerate(smiles):
        assert trajectory.top.residue(index).name == amino_residues[smiles]
예제 #7
0
def test_packmol_box_size():

    from openff.toolkit.topology import Molecule

    molecules = [Molecule.from_smiles("O")]

    trajectory, _ = packmol.pack_box(molecules, [10],
                                     box_size=([20] * 3) * unit.angstrom)

    assert trajectory is not None

    assert trajectory.n_chains == 1
    assert trajectory.n_residues == 10
    assert trajectory.n_atoms == 30
    assert trajectory.topology.n_bonds == 20

    assert all(x.name == "HOH" for x in trajectory.top.residues)

    assert np.allclose(trajectory.unitcell_lengths, 2.2)
예제 #8
0
def test_packmol_water():

    from openff.toolkit.topology import Molecule

    molecules = [Molecule.from_smiles("O")]

    trajectory, _ = packmol.pack_box(
        molecules,
        [10],
        mass_density=1.0 * unit.grams / unit.milliliters,
    )

    assert trajectory is not None

    assert trajectory.n_chains == 1
    assert trajectory.n_residues == 10
    assert trajectory.n_atoms == 30
    assert trajectory.topology.n_bonds == 20

    assert all(x.name == "HOH" for x in trajectory.top.residues)
예제 #9
0
def compare_condensed_systems(mol, force_field):
    from openff.evaluator import unit as evaluator_unit
    from openff.evaluator.utils.packmol import pack_box

    mass_density = 500 * evaluator_unit.kilogram / evaluator_unit.meter ** 3

    trj, assigned_residue_names = pack_box(
        molecules=[mol], number_of_copies=[100], mass_density=mass_density
    )

    try:
        openff_top = Topology.from_openmm(trj.top.to_openmm(), unique_molecules=[mol])
    except ValueError:
        print(f"Molecule failed! (conversion from OpenMM)\t{mol.to_inchi()}")
        return

    box_vectors = trj.unitcell_vectors[0] * simtk_unit.nanometer
    openff_top.box_vectors = box_vectors

    try:
        toolkit_sys = force_field.create_openmm_system(
            openff_top,
            charge_from_molecules=[mol],
        )

    except (
        UnassignedBondParameterException,
        UnassignedAngleParameterException,
        UnassignedProperTorsionParameterException,
    ):
        print(f"Molecule failed! (missing valence parameters)\t{mol.to_inchi()}")
        return

    positions = trj.xyz[0] * simtk_unit.nanometer
    toolkit_energy = _get_openmm_energies(
        toolkit_sys,
        box_vectors=box_vectors,
        positions=positions,
    )

    openff_sys = Interchange.from_smirnoff(force_field=force_field, topology=openff_top)
    openff_sys.box = box_vectors
    openff_sys.positions = trj.xyz[0] * unit.nanometer

    new_sys = openff_sys.to_openmm(combine_nonbonded_forces=True)

    system_energy = _get_openmm_energies(
        new_sys,
        box_vectors=box_vectors,
        positions=positions,
    )

    # Where energies to not precisely match, inspect all parameters in each force
    try:
        toolkit_energy.compare(
            system_energy,
            custom_tolerances={
                "Bond": 1e-6 * kj_mol,
                "Angle": 1e-6 * kj_mol,
                "Torsion": 4e-5 * kj_mol,
                "Nonbonded": 1e-5 * kj_mol,
            },
        )
    except EnergyError as e:
        if "Torsion" in str(e):
            _compare_torsion_forces(
                _get_force(toolkit_sys, openmm.PeriodicTorsionForce),
                _get_force(new_sys, openmm.PeriodicTorsionForce),
            )
        if "Nonbonded" in str(e):
            _compare_nonbonded_settings(
                _get_force(toolkit_sys, openmm.NonbondedForce),
                _get_force(new_sys, openmm.NonbondedForce),
            )
            _compare_nonbonded_parameters(
                _get_force(toolkit_sys, openmm.NonbondedForce),
                _get_force(new_sys, openmm.NonbondedForce),
            )
        if "Bond" in str(e):
            raise e
        if "Angle" in str(e):
            raise e