Beispiel #1
0
    def test_chemical_environments_matches_OE(self):
        """Test Topology.chemical_environment_matches"""
        from simtk.openmm import app

        toolkit_wrapper = OpenEyeToolkitWrapper()
        pdbfile = app.PDBFile(
            get_data_file_path(
                "systems/packmol_boxes/cyclohexane_ethanol_0.4_0.6.pdb"))
        # toolkit_wrapper = RDKitToolkitWrapper()
        molecules = [
            Molecule.from_file(get_data_file_path(name))
            for name in ("molecules/ethanol.mol2",
                         "molecules/cyclohexane.mol2")
        ]
        topology = Topology.from_openmm(pdbfile.topology,
                                        unique_molecules=molecules)
        # Test for substructure match
        matches = topology.chemical_environment_matches(
            "[C:1]-[C:2]-[O:3]", toolkit_registry=toolkit_wrapper)
        assert len(matches) == 143
        assert matches[0].topology_atom_indices == (1728, 1729, 1730)
        # Test for whole-molecule match
        matches = topology.chemical_environment_matches(
            "[H][C:1]([H])([H])-[C:2]([H])([H])-[O:3][H]",
            toolkit_registry=toolkit_wrapper,
        )
        assert (len(matches) == 1716
                )  # 143 * 12 (there are 12 possible hydrogen mappings)
        assert matches[0].topology_atom_indices == (1728, 1729, 1730)
        # Search for a substructure that isn't there
        matches = topology.chemical_environment_matches(
            "[C][C:1]-[C:2]-[O:3]", toolkit_registry=toolkit_wrapper)
        assert len(matches) == 0
Beispiel #2
0
def test_reference(constrained, mol):
    """Minimal regression test comparing molecule energies to energies computed
    by version 0.8.0 of the toolkit"""
    # TODO: Also test periodic vs. vacuum
    with open(get_data_file_path("reference_energies/reference_0.8.0.json"),
              "r") as fi:
        reference = json.loads(fi.read())

    name = mol + "_"
    if not constrained:
        name += "un"
    name += "constrained"
    reference_energy = reference[name]

    omm_sys, positions, off_top = _build_system(
        mol=mol,
        constrained=constrained,
    )

    simulation = _build_simulation(omm_sys=omm_sys, off_top=off_top)
    derived_energy = _get_energy(simulation=simulation, positions=positions)

    np.testing.assert_almost_equal(
        actual=derived_energy / unit.kilojoule_per_mole,
        desired=reference_energy,
        decimal=5,
    )
Beispiel #3
0
    def test_to_file_vsites(self):
        """
        Checks that Topology.to_file() doesn't write vsites
        """
        from tempfile import NamedTemporaryFile

        from openff.toolkit.topology import Molecule, Topology

        mol = Molecule.from_pdb_and_smiles(
            get_data_file_path("systems/test_systems/1_ethanol.pdb"), "CCO")
        carbons = [atom for atom in mol.atoms if atom.atomic_number == 6]
        positions = mol.conformers[0]
        mol.add_bond_charge_virtual_site(
            (carbons[0], carbons[1]),
            0.1 * unit.angstrom,
            charge_increments=[0.1, 0.05] * unit.elementary_charge,
        )
        topology = Topology()
        topology.add_molecule(mol)
        count = 0
        # The file should be printed out with 9 atoms and 0 virtualsites, so we check to ensure that thtere are only 9 HETATM entries
        with NamedTemporaryFile(suffix=".pdb") as iofile:
            topology.to_file(iofile.name, positions)
            data = open(iofile.name).readlines()
            for line in data:
                if line.startswith("HETATM"):
                    count = count + 1
        assert count == 9
Beispiel #4
0
def _build_system(mol, constrained):
    if constrained:
        parsley = ForceField("openff-1.0.0.offxml")
    else:
        parsley = ForceField("openff_unconstrained-1.0.0.offxml")

    mol = Molecule.from_file(get_data_file_path("molecules/" + mol),
                             file_format="sdf")

    if type(mol) == Molecule:
        off_top = mol.to_topology()
        positions = mol.conformers[0]
    elif type(mol) == list:
        # methane_multiconformer case is a list of two mols
        off_top = Topology()
        for mol_i in mol:
            off_top.add_molecule(mol_i)
        positions = (np.vstack([mol[0].conformers[0], mol[1].conformers[0]]) *
                     unit.angstrom)

    from openff.toolkit.utils.toolkits import (
        AmberToolsToolkitWrapper,
        RDKitToolkitWrapper,
        ToolkitRegistry,
    )

    toolkit_registry = ToolkitRegistry(
        toolkit_precedence=[RDKitToolkitWrapper, AmberToolsToolkitWrapper])

    omm_sys = parsley.create_openmm_system(off_top,
                                           toolkit_registry=toolkit_registry)

    return omm_sys, positions, off_top
Beispiel #5
0
    def test_from_openmm_duplicate_unique_mol(self):
        """Check that a DuplicateUniqueMoleculeError is raised if we try to pass in two indistinguishably unique mols"""
        from simtk.openmm import app

        pdbfile = app.PDBFile(
            get_data_file_path(
                "systems/packmol_boxes/cyclohexane_ethanol_0.4_0.6.pdb"))
        molecules = [
            Molecule.from_file(get_data_file_path(name)) for name in (
                "molecules/ethanol.mol2",
                "molecules/ethanol_reordered.mol2",
                "molecules/cyclohexane.mol2",
            )
        ]
        with self.assertRaises(DuplicateUniqueMoleculeError) as context:
            topology = Topology.from_openmm(pdbfile.topology,
                                            unique_molecules=molecules)
    def test_catch_bond_order_interpolation_bonds(self):
        from openff.toolkit.tests.test_forcefield import xml_ff_bo

        forcefield = ForceField(
            get_data_file_path("test_forcefields/test_forcefield.offxml"),
            xml_ff_bo,
        )

        top = Molecule.from_smiles("CCO").to_topology()

        with pytest.raises(SMIRNOFFParameterAttributeNotImplementedError,
                           match="length_bondorder"):
            Interchange.from_smirnoff(force_field=forcefield, topology=top)
def test_unsupported_mixing_rule():
    molecules = [create_ethanol()]
    pdbfile = app.PDBFile(get_data_file_path("systems/test_systems/1_ethanol.pdb"))
    topology = OFFBioTop.from_openmm(pdbfile.topology, unique_molecules=molecules)
    topology.mdtop = md.Topology.from_openmm(topology.to_openmm())

    forcefield = ForceField("test_forcefields/test_forcefield.offxml")
    openff_sys = Interchange.from_smirnoff(force_field=forcefield, topology=topology)

    openff_sys["vdW"].mixing_rule = "geometric"

    with pytest.raises(UnsupportedExportError, match="default NonbondedForce"):
        openff_sys.to_openmm(combine_nonbonded_forces=True)
Beispiel #8
0
    def test_to_file_units_check(self):
        """
        Checks whether writing pdb with unitless positions, Angstrom positions,
        nanometer positions, result in the same output
        """
        from tempfile import NamedTemporaryFile

        from simtk.unit import nanometer

        from openff.toolkit.topology import Molecule, Topology

        topology = Topology()
        mol = Molecule.from_pdb_and_smiles(
            get_data_file_path("systems/test_systems/1_ethanol.pdb"), "CCO")
        topology.add_molecule(mol)
        positions_angstrom = mol.conformers[0]
        count = 1
        # Write the molecule to PDB and ensure that the X coordinate of the first atom is 10.172
        with NamedTemporaryFile(suffix=".pdb") as iofile:
            topology.to_file(iofile.name, positions_angstrom)
            data = open(iofile.name).readlines()
            for line in data:
                if line.startswith("HETATM") and count == 1:
                    count = count + 1
                    coord = line.split()[-6]
        assert coord == "10.172"

        # Do the same check, but feed in equivalent positions measured in nanometers and ensure the PDB is still the same
        count = 1
        coord = None
        with NamedTemporaryFile(suffix=".pdb") as iofile:
            positions_nanometer = positions_angstrom.in_units_of(nanometer)
            topology.to_file(iofile.name, positions_nanometer)
            data = open(iofile.name).readlines()
            for line in data:
                if line.startswith("HETATM") and count == 1:
                    count = count + 1
                    coord = line.split()[-6]
        assert coord == "10.172"

        count = 1
        coord = "abc"
        with NamedTemporaryFile(suffix=".pdb") as iofile:
            positions_unitless = positions_angstrom._value
            topology.to_file(iofile.name, positions_unitless)
            data = open(iofile.name).readlines()
            for line in data:
                if line.startswith("HETATM") and count == 1:
                    count = count + 1
                    coord = line.split()[-6]
        assert coord == "10.172"
Beispiel #9
0
    def test_to_file_multi_molecule_different_order(self):
        """
        Checks for the following if Topology.to_write maintains the order of atoms
         for the same molecule with different indexing
        """
        from tempfile import NamedTemporaryFile

        from openff.toolkit.tests.test_forcefield import (
            create_ethanol,
            create_reversed_ethanol,
        )
        from openff.toolkit.topology import Molecule, Topology

        topology = Topology()
        topology.add_molecule(create_ethanol())
        topology.add_molecule(create_reversed_ethanol())
        mol = Molecule.from_pdb_and_smiles(
            get_data_file_path("systems/test_systems/1_ethanol.pdb"), "CCO")
        positions = mol.conformers[0]
        # Make up coordinates for the second ethanol by translating the first by 10 angstroms
        # (note that this will still be a gibberish conformation, since the atom order in the second molecule is different)
        positions = np.concatenate(
            [positions, positions + 10.0 * unit.angstrom])
        element_order = []

        with NamedTemporaryFile(suffix=".pdb") as iofile:
            topology.to_file(iofile.name, positions)
            data = open(iofile.name).readlines()
            for line in data:
                if line.startswith("HETATM"):
                    element_order.append(line.strip()[-1])
        assert element_order == [
            "C",
            "C",
            "O",
            "H",
            "H",
            "H",
            "H",
            "H",
            "H",
            "H",
            "H",
            "H",
            "H",
            "H",
            "H",
            "O",
            "C",
            "C",
        ]
    def test_catch_virtual_sites(self):
        from openff.toolkit.tests.test_forcefield import TestForceFieldVirtualSites

        forcefield = ForceField(
            get_data_file_path("test_forcefields/test_forcefield.offxml"),
            TestForceFieldVirtualSites.
            xml_ff_virtual_sites_monovalent_match_once,
        )

        top = Molecule.from_smiles("CCO").to_topology()

        with pytest.raises(SMIRNOFFHandlersNotImplementedError,
                           match="VirtualSites"):
            Interchange.from_smirnoff(force_field=forcefield, topology=top)
Beispiel #11
0
    def test_from_openmm_missing_reference(self):
        """Test creation of an OpenFF Topology object from an OpenMM Topology when missing a unique molecule"""
        from simtk.openmm import app

        pdbfile = app.PDBFile(
            get_data_file_path(
                "systems/packmol_boxes/cyclohexane_ethanol_0.4_0.6.pdb"))

        molecules = [create_ethanol()]
        with pytest.raises(
                ValueError,
                match="No match found for molecule C6H12") as excinfo:
            topology = Topology.from_openmm(pdbfile.topology,
                                            unique_molecules=molecules)
Beispiel #12
0
    def test_to_file_fileformat_invalid(self):
        """
        Checks for invalid file format
        """
        from openff.toolkit.topology import Molecule, Topology

        topology = Topology()
        mol = Molecule.from_pdb_and_smiles(
            get_data_file_path("systems/test_systems/1_ethanol.pdb"), "CCO")
        topology.add_molecule(mol)
        positions = mol.conformers[0]
        fname = "ethanol_file.pdb"
        with pytest.raises(NotImplementedError):
            topology.to_file(fname, positions, file_format="AbC")
def test_openmm_nonbonded_methods(inputs):
    """See test_nonbonded_method_resolution in openff/toolkit/tests/test_forcefield.py"""
    vdw_method = inputs["vdw_method"]
    electrostatics_method = inputs["electrostatics_method"]
    periodic = inputs["periodic"]
    result = inputs["result"]

    molecules = [create_ethanol()]
    forcefield = ForceField("test_forcefields/test_forcefield.offxml")

    pdbfile = app.PDBFile(get_data_file_path("systems/test_systems/1_ethanol.pdb"))
    topology = Topology.from_openmm(pdbfile.topology, unique_molecules=molecules)

    if not periodic:
        topology.box_vectors = None

    if type(result) == int:
        nonbonded_method = result
        # The method is validated and may raise an exception if it's not supported.
        forcefield.get_parameter_handler("vdW", {}).method = vdw_method
        forcefield.get_parameter_handler(
            "Electrostatics", {}
        ).method = electrostatics_method
        openff_interchange = Interchange.from_smirnoff(
            force_field=forcefield, topology=topology
        )
        openmm_system = openff_interchange.to_openmm(combine_nonbonded_forces=True)
        for force in openmm_system.getForces():
            if isinstance(force, openmm.NonbondedForce):
                assert force.getNonbondedMethod() == nonbonded_method
                break
        else:
            raise Exception
    elif issubclass(result, (BaseException, Exception)):
        exception = result
        forcefield.get_parameter_handler("vdW", {}).method = vdw_method
        forcefield.get_parameter_handler(
            "Electrostatics", {}
        ).method = electrostatics_method
        openff_interchange = Interchange.from_smirnoff(
            force_field=forcefield, topology=topology
        )
        with pytest.raises(exception):
            openff_interchange.to_openmm(combine_nonbonded_forces=True)
    else:
        raise Exception("uh oh")
Beispiel #14
0
    def test_from_openmm(self):
        """Test creation of an OpenFF Topology object from an OpenMM Topology and component molecules"""
        from simtk.openmm import app

        pdbfile = app.PDBFile(
            get_data_file_path(
                "systems/packmol_boxes/cyclohexane_ethanol_0.4_0.6.pdb"))

        with pytest.raises(MissingUniqueMoleculesError,
                           match="requires a list of Molecule objects"):
            Topology.from_openmm(pdbfile.topology)

        molecules = [create_ethanol(), create_cyclohexane()]

        topology = Topology.from_openmm(pdbfile.topology,
                                        unique_molecules=molecules)
        assert topology.n_reference_molecules == 2
        assert topology.n_topology_molecules == 239
Beispiel #15
0
    def test_from_mdtraj(self):
        """Test construction of an OpenFF Topology from an MDTraj Topology object"""
        import mdtraj as md

        pdb_path = get_data_file_path(
            "systems/test_systems/1_cyclohexane_1_ethanol.pdb")
        trj = md.load(pdb_path)

        with pytest.raises(MissingUniqueMoleculesError,
                           match="requires a list of Molecule objects"):
            Topology.from_mdtraj(trj.top)

        unique_molecules = [
            Molecule.from_smiles(mol_name) for mol_name in ["C1CCCCC1", "CCO"]
        ]
        top = Topology.from_mdtraj(trj.top, unique_molecules=unique_molecules)

        assert top.n_topology_molecules == 2
        assert top.n_topology_bonds == 26
Beispiel #16
0
    def test_to_file_fileformat_lettercase(self):
        """
        Checks if fileformat specifier is indpendent of upper/lowercase
        """
        from tempfile import NamedTemporaryFile

        from openff.toolkit.topology import Molecule, Topology

        topology = Topology()
        mol = Molecule.from_pdb_and_smiles(
            get_data_file_path("systems/test_systems/1_ethanol.pdb"), "CCO")
        topology.add_molecule(mol)
        positions = mol.conformers[0]
        count = 1
        with NamedTemporaryFile(suffix=".pdb") as iofile:
            topology.to_file(iofile.name, positions, file_format="pDb")
            data = open(iofile.name).readlines()
            for line in data:
                if line.startswith("HETATM") and count == 1:
                    count = count + 1
                    coord = line.split()[-6]
        assert coord == "10.172"
Beispiel #17
0
    def test_from_openmm_missing_conect(self):
        """
        Test creation of an OpenFF Topology object from an OpenMM Topology
        when the origin PDB lacks CONECT records
        """
        from simtk.openmm import app

        pdbfile = app.PDBFile(
            get_data_file_path("systems/test_systems/1_ethanol_no_conect.pdb"))

        molecules = []
        molecules.append(Molecule.from_smiles("CCO"))
        with pytest.raises(
                ValueError,
                match="No match found for molecule C. This would be a "
                "very unusual molecule to try and parameterize, "
                "and it is likely that the data source it was "
                "read from does not contain connectivity "
                "information. If this molecule is coming from "
                "PDB, please ensure that the file contains CONECT "
                "records.",
        ) as excinfo:
            topology = Topology.from_openmm(pdbfile.topology,
                                            unique_molecules=molecules)
Beispiel #18
0
    def setUp(self):
        self.empty_molecule = Molecule()
        self.ethane_from_smiles = Molecule.from_smiles("CC")
        self.ethene_from_smiles = Molecule.from_smiles("C=C")
        self.propane_from_smiles = Molecule.from_smiles("CCC")

        filename = get_data_file_path("molecules/toluene.sdf")
        self.toluene_from_sdf = Molecule.from_file(filename)
        if OpenEyeToolkitWrapper.is_available():
            filename = get_data_file_path("molecules/toluene_charged.mol2")
            # TODO: This will require openeye to load
            self.toluene_from_charged_mol2 = Molecule.from_file(filename)
        self.charged_methylamine_from_smiles = Molecule.from_smiles(
            "[H]C([H])([H])[N+]([H])([H])[H]")

        molecule = Molecule.from_smiles("CC")
        carbons = [atom for atom in molecule.atoms if atom.atomic_number == 6]
        c0_hydrogens = [
            atom for atom in carbons[0].bonded_atoms if atom.atomic_number == 1
        ]
        molecule.add_bond_charge_virtual_site(
            (carbons[0], carbons[1]),
            0.1 * unit.angstrom,
            charge_increments=[0.1, 0.05] * unit.elementary_charge,
        )
        molecule.add_monovalent_lone_pair_virtual_site(
            (c0_hydrogens[0], carbons[0], carbons[1]),
            0.2 * unit.angstrom,
            20 * unit.degree,
            25 * unit.degree,
            charge_increments=[0.01, 0.02, 0.03] * unit.elementary_charge,
        )
        self.ethane_from_smiles_w_vsites = Molecule(molecule)

        # Make a propane with virtual sites
        molecule = Molecule.from_smiles("CCC")
        carbons = [atom for atom in molecule.atoms if atom.atomic_number == 6]
        c0_hydrogens = [
            atom for atom in carbons[0].bonded_atoms if atom.atomic_number == 1
        ]
        # This will add *two* particles (symmetric=True), *one* virtual site
        molecule.add_monovalent_lone_pair_virtual_site(
            (c0_hydrogens[0], carbons[0], carbons[1]),
            0.2 * unit.angstrom,
            20 * unit.degree,
            25 * unit.degree,
            charge_increments=[0.01, 0.02, 0.03] * unit.elementary_charge,
            symmetric=True,
        )
        # This will add *one* particle (symmetric=False), *one* virtual site
        molecule.add_bond_charge_virtual_site(
            (carbons[0], carbons[1]),
            0.1 * unit.angstrom,
            charge_increments=[0.1, 0.05] * unit.elementary_charge,
            symmetric=False,
        )
        self.propane_from_smiles_w_vsites = Molecule(molecule)

        # Make a TIP5 water
        molecule = Molecule.from_smiles("[H][O][H]")
        O1 = [atom for atom in molecule.atoms if atom.atomic_number == 8][0]
        H1, H2 = [atom for atom in O1.bonded_atoms if atom.atomic_number == 1]
        molecule.add_divalent_lone_pair_virtual_site(
            (H1, O1, H2),
            0.7 * unit.angstrom,
            54.71384225 * unit.degree,
            charge_increments=[0.1205, 0.00, 0.1205] * unit.elementary_charge,
            symmetric=True,
        )
        self.tip5_water = Molecule(molecule)
versus energies from AMBER .prmtop and .crd files (parm@frosst params).
"""

import os
import glob

# datapath = './AlkEthOH_tripos/AlkEthOH_chain_filt1'
# datapath = './AlkEthOH_tripos/AlkEthOH_rings_filt1'
datapath = './AlkEthOH_tripos/AlkEthOH_test_filt1'

# Check if we have this data file; if not we have to extract the archive.
if not os.path.isdir(datapath):
    print("Extracting archived molecule files.")
    # Extract the AlkEthOH dataset shipped with the toolkit in data/molecules/ in the working directory.
    from openff.toolkit.tests.utils import get_data_file_path
    tarfile_path = os.path.join(get_data_file_path('molecules'),
                                'AlkEthOH_tripos.tar.gz')
    import tarfile
    with tarfile.open(tarfile_path, 'r:gz') as tar:
        tar.extractall()

#Obtain list of molecules
mol_filepaths = glob.glob(datapath + '/*tripos.mol2')
mol_filepaths = [fnm for fnm in mol_filepaths
                 if not 'c1302' in fnm]  # Skip water.

print('Found {} files to test'.format(len(mol_filepaths)))

# Load force field
from openff.toolkit.typing.engines.smirnoff import ForceField
forcefield = ForceField('test_forcefields/Frosst_AlkEthOH_parmAtFrosst.offxml')