Example #1
0
def apply_forcefield(structure, forcefield, debug=False):
    """Apply a forcefield to a Topology. """
    if not structure.bonds:
        warn("Structure contains no bonds: \n{}\n".format(structure))
    if isinstance(forcefield, string_types):
        if forcefield.lower() in ["opls-aa", "oplsaa", "opls"]:
            if os.path.isdir("oplsaa.ff"):
                ff_path = "oplsaa.ff/forcefield.itp"
            else:
                ff_path = os.path.join(gmx.GROMACS_TOPDIR, "oplsaa.ff/forcefield.itp")
        elif forcefield.lower() in ["trappeua"]:
            ff_path = os.path.join(gmx.GROMACS_TOPDIR, "trappeua.ff/forcefield.itp")
        else:
            ff_path = forcefield
            # TODO: this is a patchwork fix until rules and FF files become one
            forcefield = forcefield.lower()
            for alias in OPLS_ALIASES:
                if alias in forcefield:
                    forcefield = "oplsaa"
        ff = GromacsTopologyFile(ff_path, parametrize=False)

    find_atomtypes(structure.atoms, forcefield, debug=debug)

    if hasattr(structure, "box"):
        ff.box = structure.box
    ff.atoms = structure.atoms
    ff.bonds = structure.bonds
    ff.residues = structure.residues
    create_bonded_forces(ff)
    ff.parametrize()
    return ff
Example #2
0
    def _run_atomtyping(self, top, use_residue_map=True, **kwargs):
        """Atomtype the topology.

        Parameters
        ----------
        top : gmso.Topology
            Molecular Topology to be atomtyped.
        use_residue_map : bool, optional, default=True
            A speed-up option that utilizes previously atom typed
            molecules as a template for future atom typing of
            identical molecules, instead of reevaluating them each
            individually. To be implemented
        """
        if isinstance(top, mb.Compound):
            top = from_mbuild(top)
        # TO DO in another PR
        if use_residue_map:
            # Detect duplicates subtopology/residues
            # (do matching by name, assert same number
            # of atoms)
            # Not implemented yet
            typemap = find_atomtypes(top, forcefield=self)
        else:
            typemap = find_atomtypes(top, forcefield=self)

        return typemap
 def test_atom_typing(
     self, openff_topology_graph, gmso_topology_graph, parmed_topology_graph
 ):
     # ToDo: More robust testing for atomtyping
     opls = Forcefield(name="oplsaa")
     openff_typemap = find_atomtypes(openff_topology_graph, forcefield=opls)
     gmso_typemap = find_atomtypes(gmso_topology_graph, forcefield=opls)
     parmed_typemap = find_atomtypes(parmed_topology_graph, forcefield=opls)
     assert openff_typemap
     assert gmso_typemap
     assert parmed_typemap
Example #4
0
def apply_forcefield(intermol_system, forcefield, debug=True):
    """Apply a forcefield to a Topology. """
    if forcefield.lower() in ['opls-aa', 'oplsaa', 'opls']:
        ff = Forcefield('oplsaa')
    else:
        raise ValueError("Unsupported forcefield: '{0}'".format(forcefield))

    bondgraph = prepare_atoms(intermol_system)
    # Nodes are tuples of (atom, moleculetype).
    atoms = [atom for atom, _ in bondgraph.nodes()]
    find_atomtypes(atoms, forcefield, debug=debug)
    ff.resolve_bondingtypes(bondgraph)
    propogate_atomtyping(intermol_system)
    enumerate_forcefield_terms(intermol_system, bondgraph, ff)
    import ipdb; ipdb.set_trace()
    intermol_system.gen_pairs(n_excl=4)
    ff = ff.prune()
Example #5
0
    def test_atomtyping(self, only_run=None):
        resource_dir = resource_filename('foyer', '../opls_validation')
        top_files = glob.glob(os.path.join(resource_dir, '*.top'))

        # Please update this file if you implement atom typing for a test case.
        implemented_tests_path = os.path.join(os.path.dirname(__file__),
                                              'implemented_opls_tests.txt')
        correctly_implemented = [
            line.strip() for line in open(implemented_tests_path)
        ]

        for top in top_files:
            top_name = os.path.split(top)[-1]
            system, known_opls_types, mol_name = load_top_opls(top, only_run)

            if only_run and only_run != mol_name:
                continue
            elif mol_name not in correctly_implemented:
                continue

            print("Typing {} ({})...".format(mol_name, top_name))
            prepare_atoms(system)
            find_atomtypes(list(system.atoms),
                           forcefield='OPLS-AA',
                           debug=False)

            generated_opls_types = list()

            for i, atom in enumerate(system.atoms):
                message = (
                    'Found multiple or no OPLS types for atom {} in {} ({}): {}\n'
                    'Should be atomtype: {}'.format(i, mol_name, top_name,
                                                    atom.atomtype[0],
                                                    known_opls_types[i]))
                assert isinstance(atom.atomtype[0], string_types), message
                generated_opls_types.append(atom.atomtype[0])
            both = zip(generated_opls_types, known_opls_types)
            message = "Found inconsistent OPLS types in {} ({}): {}".format(
                mol_name, top_name,
                list(
                    zip(range(len(generated_opls_types)), generated_opls_types,
                        known_opls_types)))

            assert all([a == b for a, b in both]), message
            print("Passed.\n")
Example #6
0
    def run_atomtyping(self, structure, use_residue_map=True, **kwargs):
        """Atomtype the topology

        Parameters
        ----------
        structure : parmed.structure.Structure
            Molecular structure to find atom types of
        use_residue_map : boolean, optional, default=True
            Store atomtyped topologies of residues to a dictionary that maps
            them to residue names.  Each topology, including atomtypes, will be
            copied to other residues with the same name. This avoids repeatedly
            calling the subgraph isomorphism on idential residues and should
            result in better performance for systems with many identical
            residues, i.e. a box of water. Note that for this to be applied to
            independent molecules, they must each be saved as different
            residues in the topology.
        """

        if use_residue_map:
            independent_residues = _check_independent_residues(structure)

            if independent_residues:
                residue_map = dict()

                # Need to call this only once and store results for later id() comparisons
                for res_id, res in enumerate(structure.residues):
                    if structure.residues[res_id].name not in residue_map.keys(
                    ):
                        tmp_res = _structure_from_residue(res, structure)
                        typemap = find_atomtypes(tmp_res, forcefield=self)
                        residue_map[res.name] = typemap

                typemap = _unwrap_typemap(structure, residue_map)

            else:
                typemap = find_atomtypes(structure, forcefield=self)

        else:
            typemap = find_atomtypes(structure, forcefield=self)

        return typemap
Example #7
0
    def run_atomtyping(self, topology, use_residue_map=True):
        """Atomtype the topology

        Parameters
        ----------
        topology : openmm.app.Topology
            Molecular structure to find atom types of
        use_residue_map : boolean, optional, default=True
            Store atomtyped topologies of residues to a dictionary that maps
            them to residue names.  Each topology, including atomtypes, will be
            copied to other residues with the same name. This avoids repeatedly
            calling the subgraph isomorphism on idential residues and should
            result in better performance for systems with many identical
            residues, i.e. a box of water. Note that for this to be applied to
            independent molecules, they must each be saved as different
            residues in the topology.
        """
        if use_residue_map:
            independent_residues = _check_independent_residues(topology)

            if independent_residues:
                residue_map = dict()

                for res in topology.residues():
                    if res.name not in residue_map.keys():
                        residue = _topology_from_residue(res)
                        typemap = find_atomtypes(residue, forcefield=self)
                        residue_map[res.name] = typemap

                typemap = _unwrap_typemap(topology, residue_map)

            else:
                typemap = find_atomtypes(topology, forcefield=self)

        else:
            typemap = find_atomtypes(topology, forcefield=self)

        if not all([a.id for a in topology.atoms()][0]):
            raise ValueError('Not all atoms in topology have atom types')

        return typemap
Example #8
0
    def store_matches(
        self,
        force_field: "Forcefield",
        topology: "OFFBioTop",
    ) -> None:
        """Populate slotmap with key-val pairs of slots and unique potential Identifiers"""
        from foyer.atomtyper import find_atomtypes

        top_graph = TopologyGraph.from_openff_topology(
            openff_topology=topology)
        type_map = find_atomtypes(top_graph, forcefield=force_field)
        for key, val in type_map.items():
            top_key = TopologyKey(atom_indices=(key, ))
            self.slot_map[top_key] = PotentialKey(id=val["atomtype"])
Example #9
0
def apply_forcefield(intermol_system, forcefield, debug=True):
    """Apply a forcefield to a Topology. """
    if forcefield.lower() in ['opls-aa', 'oplsaa', 'opls']:
        ff = Forcefield('oplsaa')
    elif forcefield.lower() in ['trappeua']:
        ff = Forcefield('trappeua')
    else:
        raise ValueError("Unsupported forcefield: '{0}'".format(forcefield))

    bondgraph = prepare_atoms(intermol_system)
    # Nodes are tuples of (atom, moleculetype).
    atoms = [atom for atom, _ in bondgraph.nodes()]
    find_atomtypes(atoms, forcefield, debug=debug)
    ff.resolve_bondingtypes(bondgraph)
    propogate_atomtyping(intermol_system)
    enumerate_forcefield_terms(intermol_system, bondgraph, ff)

    # Copy over defaults.
    intermol_system.nonbonded_function = ff.system.nonbonded_function
    intermol_system.combination_rule = ff.system.combination_rule
    intermol_system.genpairs = ff.system.genpairs
    intermol_system.lj_correction = ff.system.lj_correction
    intermol_system.coulomb_correction = ff.system.coulomb_correction
Example #10
0
    def test_atomtyping(self, top_path):
        top_path = os.path.join(self.resource_dir, top_path)

        base_path, top_filename = os.path.split(top_path)
        gro_file = '{}-gas.gro'.format(top_filename[:-4])
        gro_path = os.path.join(base_path, gro_file)

        structure = pmd.gromacs.GromacsTopologyFile(top_path, xyz=gro_path,
                                                    parametrize=False)
        structure.title = structure.title.replace(' GAS', '')
        known_opls_types = [atom.type for atom in structure.atoms]

        print("Typing {} ({})...".format(structure.title, top_filename))
        find_atomtypes(structure.atoms, forcefield='OPLS-AA', debug=False)

        generated_opls_types = list()
        for i, atom in enumerate(structure.atoms):
            message = ('Found multiple or no OPLS types for atom {} in {} ({}): {}\n'
                       'Should be atomtype: {}'.format(
                i, structure.title, top_filename, atom.type, known_opls_types[i]))
            assert atom.type, message

            generated_opls_types.append(atom.type)
        both = zip(generated_opls_types, known_opls_types)

        n_types = np.array(range(len(generated_opls_types)))
        known_opls_types = np.array(known_opls_types)
        generated_opls_types = np.array(generated_opls_types)

        non_matches = np.array([a != b for a, b in both])
        message = "Found inconsistent OPLS types in {} ({}): {}".format(
            structure.title, top_filename,
            list(zip(n_types[non_matches],
                     generated_opls_types[non_matches],
                     known_opls_types[non_matches])))
        assert not non_matches.any(), message
        return structure.title
Example #11
0
    def test_atomtyping(self, only_run=None):
        resource_dir = resource_filename('foyer', '../opls_validation')
        top_files = glob.glob(os.path.join(resource_dir, '*.top'))

        # Please update this file if you implement atom typing for a test case.
        implemented_tests_path = os.path.join(os.path.dirname(__file__), 'implemented_opls_tests.txt')
        correctly_implemented = [line.strip() for line in open(implemented_tests_path)]

        for top in top_files:
            top_name = os.path.split(top)[-1]
            system, known_opls_types, mol_name = load_top_opls(top, only_run)

            if only_run and only_run != mol_name:
                continue
            elif mol_name not in correctly_implemented:
                continue

            print("Typing {} ({})...".format(mol_name, top_name))
            prepare_atoms(system)
            find_atomtypes(list(system.atoms), forcefield='OPLS-AA', debug=False)

            generated_opls_types = list()

            for i, atom in enumerate(system.atoms):
                message = ('Found multiple or no OPLS types for atom {} in {} ({}): {}\n'
                           'Should be atomtype: {}'.format(
                    i, mol_name, top_name, atom.atomtype[0], known_opls_types[i]))
                assert isinstance(atom.atomtype[0], string_types), message
                generated_opls_types.append(atom.atomtype[0])
            both = zip(generated_opls_types, known_opls_types)
            message = "Found inconsistent OPLS types in {} ({}): {}".format(
                mol_name, top_name, list(zip(range(len(generated_opls_types)),
                                        generated_opls_types,
                                        known_opls_types)))

            assert all([a == b for a, b in both]), message
            print("Passed.\n")
Example #12
0
    def run_atomtyping(self, topology, use_residue_map=True):
        """Atomtype the topology

        Parameters
        ----------
        topology : openmm.app.Topology
            Molecular structure to find atom types of
        use_residue_map : boolean, optional, default=True
            Store atomtyped topologies of residues to a dictionary that maps
            them to residue names.  Each topology, including atomtypes, will be
            copied to other residues with the same name. This avoids repeatedly
            calling the subgraph isomorphism on idential residues and should
            result in better performance for systems with many identical
            residues, i.e. a box of water. Note that for this to be applied to
            independent molecules, they must each be saved as different
            residues in the topology.
        """
        if use_residue_map:
            independent_residues = _check_independent_residues(topology)

            if independent_residues:
                residue_map = dict()

                for res in topology.residues():
                    if res.name not in residue_map.keys():
                        residue = _topology_from_residue(res)
                        find_atomtypes(residue, forcefield=self)
                        residue_map[res.name] = residue

                for key, val in residue_map.items():
                    _update_atomtypes(topology, key, val)

            else:
                find_atomtypes(topology, forcefield=self)

        else:
            find_atomtypes(topology, forcefield=self)

        if not all([a.id for a in topology.atoms()][0]):
            raise ValueError('Not all atoms in topology have atom types')

        return topology
Example #13
0
    from pkg_resources import resource_filename

    fn = resource_filename('mbuild',
                           os.path.join('..', 'opls_validation', name))
    if not os.path.exists(fn):
        raise ValueError('Sorry! {} does not exists. If you just '
                         'added it, you\'ll have to re-install'.format(fn))
    return fn


if __name__ == "__main__":
    import mbuild as mb
    from foyer.atomtyper import find_atomtypes
    from foyer.forcefield import prepare_atoms

    # m = Methane()
    # m = Ethane()
    # m = mb.load(get_opls_fn('isopropane.pdb'))
    # m = mb.load(get_opls_fn('cyclohexane.pdb'))
    # m = mb.load(get_opls_fn('neopentane.pdb'))
    m = mb.load(get_opls_fn('benzene.pdb'))
    # m = mb.load(get_opls_fn('1-propene.pdb'))
    # m = mb.load(get_opls_fn('biphenyl.pdb'))

    traj = m.to_trajectory()
    prepare_atoms(traj.top)
    find_atomtypes(traj.top._atoms, forcefield='OPLS-AA')

    for i, a in enumerate(traj.top._atoms):
        print("Atom name={}, opls_type={}".format(a.name, a.atomtype))
Example #14
0
    def createSystem(self, topology, nonbondedMethod=NoCutoff,
                     nonbondedCutoff=1.0*u.nanometer, constraints=None,
                     rigidWater=True, removeCMMotion=True, hydrogenMass=None,
                     **args):
        """Construct an OpenMM System representing a Topology with this force field.

        Parameters
        ----------
        topology : Topology
            The Topology for which to create a System
        nonbondedMethod : object=NoCutoff
            The method to use for nonbonded interactions.  Allowed values are
            NoCutoff, CutoffNonPeriodic, CutoffPeriodic, Ewald, or PME.
        nonbondedCutoff : distance=1*nanometer
            The cutoff distance to use for nonbonded interactions
        constraints : object=None
            Specifies which bonds and angles should be implemented with constraints.
            Allowed values are None, HBonds, AllBonds, or HAngles.
        rigidWater : boolean=True
            If true, water molecules will be fully rigid regardless of the value
            passed for the constraints argument
        removeCMMotion : boolean=True
            If true, a CMMotionRemover will be added to the System
        hydrogenMass : mass=None
            The mass to use for hydrogen atoms bound to heavy atoms.  Any mass
            added to a hydrogen is subtracted from the heavy atom to keep
            their total mass the same.
        args
             Arbitrary additional keyword arguments may also be specified.
             This allows extra parameters to be specified that are specific to
             particular force fields.

        Returns
        -------
        system
            the newly created System
        """

        # Atomtype the system.
        G = nx.Graph()
        G.add_nodes_from(topology.atoms())
        G.add_edges_from(topology.bonds())
        cycles = nx.cycle_basis(G)

        for atom in topology.atoms():
            atom.cycles = set()

        for cycle in cycles:
            for atom in cycle:
                atom.cycles.add(tuple(cycle))

        find_atomtypes(atoms=list(topology.atoms()), forcefield=self)

        data = app.ForceField._SystemData()
        data.atoms = list(topology.atoms())
        for atom in data.atoms:
            data.excludeAtomWith.append([])

        # Make a list of all bonds
        for bond in topology.bonds():
            data.bonds.append(app.ForceField._BondData(bond[0].index, bond[1].index))

        # Record which atoms are bonded to each other atom
        bondedToAtom = []
        for i in range(len(data.atoms)):
            bondedToAtom.append(set())
            data.atomBonds.append([])
        for i in range(len(data.bonds)):
            bond = data.bonds[i]
            bondedToAtom[bond.atom1].add(bond.atom2)
            bondedToAtom[bond.atom2].add(bond.atom1)
            data.atomBonds[bond.atom1].append(i)
            data.atomBonds[bond.atom2].append(i)

        # TODO: Better way to lookup nonbonded parameters...?
        nonbonded_params = None
        for generator in self.getGenerators():
            if isinstance(generator, NonbondedGenerator):
                nonbonded_params = generator.params.paramsForType
                break

        for chain in topology.chains():
            for res in chain.residues():
                for atom in res.atoms():
                    data.atomType[atom] = atom.id
                    if nonbonded_params:
                        params = nonbonded_params[atom.id]
                        data.atomParameters[atom] = params

        # Create the System and add atoms
        sys = mm.System()
        for atom in topology.atoms():
            # Look up the atom type name, returning a helpful error message if it cannot be found.
            if atom not in data.atomType:
                raise Exception("Could not identify atom type for atom '%s'." % str(atom))
            typename = data.atomType[atom]

            # Look up the type name in the list of registered atom types, returning a helpful error message if it cannot be found.
            if typename not in self._atomTypes:
                msg  = "Could not find typename '%s' for atom '%s' in list of known atom types.\n" % (typename, str(atom))
                msg += "Known atom types are: %s" % str(self._atomTypes.keys())
                raise Exception(msg)

            # Add the particle to the OpenMM system.
            mass = self._atomTypes[typename].mass
            sys.addParticle(mass)

        # Adjust hydrogen masses if requested.
        if hydrogenMass is not None:
            if not u.is_quantity(hydrogenMass):
                hydrogenMass *= u.dalton
            for atom1, atom2 in topology.bonds():
                if atom1.element == elem.hydrogen:
                    (atom1, atom2) = (atom2, atom1)
                if atom2.element == elem.hydrogen and atom1.element not in (elem.hydrogen, None):
                    transferMass = hydrogenMass-sys.getParticleMass(atom2.index)
                    sys.setParticleMass(atom2.index, hydrogenMass)
                    sys.setParticleMass(atom1.index, sys.getParticleMass(atom1.index)-transferMass)

        # Set periodic boundary conditions.
        boxVectors = topology.getPeriodicBoxVectors()
        if boxVectors is not None:
            sys.setDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2])
        elif nonbondedMethod not in [NoCutoff, CutoffNonPeriodic]:
            raise ValueError('Requested periodic boundary conditions for a Topology that does not specify periodic box dimensions')

        # Make a list of all unique angles
        uniqueAngles = set()
        for bond in data.bonds:
            for atom in bondedToAtom[bond.atom1]:
                if atom != bond.atom2:
                    if atom < bond.atom2:
                        uniqueAngles.add((atom, bond.atom1, bond.atom2))
                    else:
                        uniqueAngles.add((bond.atom2, bond.atom1, atom))
            for atom in bondedToAtom[bond.atom2]:
                if atom != bond.atom1:
                    if atom > bond.atom1:
                        uniqueAngles.add((bond.atom1, bond.atom2, atom))
                    else:
                        uniqueAngles.add((atom, bond.atom2, bond.atom1))
        data.angles = sorted(list(uniqueAngles))

        # Make a list of all unique proper torsions
        uniquePropers = set()
        for angle in data.angles:
            for atom in bondedToAtom[angle[0]]:
                if atom not in angle:
                    if atom < angle[2]:
                        uniquePropers.add((atom, angle[0], angle[1], angle[2]))
                    else:
                        uniquePropers.add((angle[2], angle[1], angle[0], atom))
            for atom in bondedToAtom[angle[2]]:
                if atom not in angle:
                    if atom > angle[0]:
                        uniquePropers.add((angle[0], angle[1], angle[2], atom))
                    else:
                        uniquePropers.add((atom, angle[2], angle[1], angle[0]))
        data.propers = sorted(list(uniquePropers))

        # Make a list of all unique improper torsions
        for atom in range(len(bondedToAtom)):
            bondedTo = bondedToAtom[atom]
            if len(bondedTo) > 2:
                for subset in itertools.combinations(bondedTo, 3):
                    data.impropers.append((atom, subset[0], subset[1], subset[2]))

        # Identify bonds that should be implemented with constraints
        if constraints == AllBonds or constraints == HAngles:
            for bond in data.bonds:
                bond.isConstrained = True
        elif constraints == HBonds:
            for bond in data.bonds:
                atom1 = data.atoms[bond.atom1]
                atom2 = data.atoms[bond.atom2]
                bond.isConstrained = atom1.name.startswith('H') or atom2.name.startswith('H')
        if rigidWater:
            for bond in data.bonds:
                atom1 = data.atoms[bond.atom1]
                atom2 = data.atoms[bond.atom2]
                if atom1.residue.name == 'HOH' and atom2.residue.name == 'HOH':
                    bond.isConstrained = True

        # Identify angles that should be implemented with constraints
        if constraints == HAngles:
            for angle in data.angles:
                atom1 = data.atoms[angle[0]]
                atom2 = data.atoms[angle[1]]
                atom3 = data.atoms[angle[2]]
                numH = 0
                if atom1.name.startswith('H'):
                    numH += 1
                if atom3.name.startswith('H'):
                    numH += 1
                data.isAngleConstrained.append(numH == 2 or (numH == 1 and atom2.name.startswith('O')))
        else:
            data.isAngleConstrained = len(data.angles)*[False]
        if rigidWater:
            for i in range(len(data.angles)):
                angle = data.angles[i]
                atom1 = data.atoms[angle[0]]
                atom2 = data.atoms[angle[1]]
                atom3 = data.atoms[angle[2]]
                if atom1.residue.name == 'HOH' and atom2.residue.name == 'HOH' and atom3.residue.name == 'HOH':
                    data.isAngleConstrained[i] = True

        # Add virtual sites
        for atom in data.virtualSites:
            (site, atoms, excludeWith) = data.virtualSites[atom]
            index = atom.index
            data.excludeAtomWith[excludeWith].append(index)
            if site.type == 'average2':
                sys.setVirtualSite(index, mm.TwoParticleAverageSite(atoms[0], atoms[1], site.weights[0], site.weights[1]))
            elif site.type == 'average3':
                sys.setVirtualSite(index, mm.ThreeParticleAverageSite(atoms[0], atoms[1], atoms[2], site.weights[0], site.weights[1], site.weights[2]))
            elif site.type == 'outOfPlane':
                sys.setVirtualSite(index, mm.OutOfPlaneSite(atoms[0], atoms[1], atoms[2], site.weights[0], site.weights[1], site.weights[2]))
            elif site.type == 'localCoords':
                sys.setVirtualSite(index, mm.LocalCoordinatesSite(atoms[0], atoms[1], atoms[2],
                                                                  mm.Vec3(site.originWeights[0], site.originWeights[1], site.originWeights[2]),
                                                                  mm.Vec3(site.xWeights[0], site.xWeights[1], site.xWeights[2]),
                                                                  mm.Vec3(site.yWeights[0], site.yWeights[1], site.yWeights[2]),
                                                                  mm.Vec3(site.localPos[0], site.localPos[1], site.localPos[2])))

        # Add forces to the System
        for force in self._forces:
            force.createForce(sys, data, nonbondedMethod, nonbondedCutoff, args)
        if removeCMMotion:
            sys.addForce(mm.CMMotionRemover())

        # Let force generators do postprocessing
        for force in self._forces:
            if 'postprocessSystem' in dir(force):
                force.postprocessSystem(sys, data, args)

        # Execute scripts found in the XML files.
        for script in self._scripts:
            exec(script, locals())
        return sys
Example #15
0
    from pkg_resources import resource_filename

    fn = resource_filename('mbuild', os.path.join('..', 'opls_validation',
                                                  name))
    if not os.path.exists(fn):
        raise ValueError('Sorry! {} does not exists. If you just '
                         'added it, you\'ll have to re-install'.format(fn))
    return fn


if __name__ == "__main__":
    import mbuild as mb
    from foyer.atomtyper import find_atomtypes
    from foyer.forcefield import prepare_atoms

    # m = Methane()
    # m = Ethane()
    # m = mb.load(get_opls_fn('isopropane.pdb'))
    # m = mb.load(get_opls_fn('cyclohexane.pdb'))
    # m = mb.load(get_opls_fn('neopentane.pdb'))
    m = mb.load(get_opls_fn('benzene.pdb'))
    # m = mb.load(get_opls_fn('1-propene.pdb'))
    # m = mb.load(get_opls_fn('biphenyl.pdb'))

    traj = m.to_trajectory()
    prepare_atoms(traj.top)
    find_atomtypes(traj.top._atoms, forcefield='OPLS-AA')

    for i, a in enumerate(traj.top._atoms):
        print("Atom name={}, opls_type={}".format(a.name, a.atomtype))
Example #16
0
def uff_C_3(atom):
    """ """
    return True


@Element("H")
@NeighborCount(1)
@NeighborsExactly("C", 1)
@Whitelist("H_")
def uff_H_(atom):
    """ """
    return True


if __name__ == "__main__":

    from foyer.atomtyper import find_atomtypes
    from foyer.forcefield import prepare_atoms

    from mbuild.examples.methane.methane import Methane

    m = Methane()
    # m = Ethane()

    traj = m.to_trajectory()
    prepare_atoms(traj.top)
    find_atomtypes(traj.top._atoms, forcefield="UFF")

    for atom in traj.top._atoms:
        print("Atom name={}, opls_type={}".format(atom.name, atom.atomtype))
Example #17
0
    def createSystem(self, topology, atomtype=True, nonbondedMethod=NoCutoff,
                     nonbondedCutoff=1.0 * u.nanometer, constraints=None,
                     rigidWater=True, removeCMMotion=True, hydrogenMass=None,
                     **args):
        """Construct an OpenMM System representing a Topology with this force field.

        Parameters
        ----------
        topology : Topology
            The Topology for which to create a System
        nonbondedMethod : object=NoCutoff
            The method to use for nonbonded interactions.  Allowed values are
            NoCutoff, CutoffNonPeriodic, CutoffPeriodic, Ewald, or PME.
        nonbondedCutoff : distance=1*nanometer
            The cutoff distance to use for nonbonded interactions
        constraints : object=None
            Specifies which bonds and angles should be implemented with constraints.
            Allowed values are None, HBonds, AllBonds, or HAngles.
        rigidWater : boolean=True
            If true, water molecules will be fully rigid regardless of the value
            passed for the constraints argument
        removeCMMotion : boolean=True
            If true, a CMMotionRemover will be added to the System
        hydrogenMass : mass=None
            The mass to use for hydrogen atoms bound to heavy atoms.  Any mass
            added to a hydrogen is subtracted from the heavy atom to keep
            their total mass the same.
        args
             Arbitrary additional keyword arguments may also be specified.
             This allows extra parameters to be specified that are specific to
             particular force fields.

        Returns
        -------
        system
            the newly created System
        """
        if atomtype:
            find_atomtypes(topology, forcefield=self)

        data = app.ForceField._SystemData()
        data.atoms = list(topology.atoms())
        for atom in data.atoms:
            data.excludeAtomWith.append([])

        # Make a list of all bonds
        for bond in topology.bonds():
            data.bonds.append(app.ForceField._BondData(bond[0].index, bond[1].index))

        # Record which atoms are bonded to each other atom
        bonded_to_atom = []
        for i in range(len(data.atoms)):
            bonded_to_atom.append(set())
            data.atomBonds.append([])
        for i in range(len(data.bonds)):
            bond = data.bonds[i]
            bonded_to_atom[bond.atom1].add(bond.atom2)
            bonded_to_atom[bond.atom2].add(bond.atom1)
            data.atomBonds[bond.atom1].append(i)
            data.atomBonds[bond.atom2].append(i)

        # TODO: Better way to lookup nonbonded parameters...?
        nonbonded_params = None
        for generator in self.getGenerators():
            if isinstance(generator, NonbondedGenerator):
                nonbonded_params = generator.params.paramsForType
                break

        for chain in topology.chains():
            for res in chain.residues():
                for atom in res.atoms():
                    data.atomType[atom] = atom.id
                    if nonbonded_params:
                        params = nonbonded_params[atom.id]
                        data.atomParameters[atom] = params

        # Create the System and add atoms
        sys = mm.System()
        for atom in topology.atoms():
            # Look up the atom type name, returning a helpful error message if it cannot be found.
            if atom not in data.atomType:
                raise Exception("Could not identify atom type for atom '%s'." % str(atom))
            typename = data.atomType[atom]

            # Look up the type name in the list of registered atom types, returning a helpful error message if it cannot be found.
            if typename not in self._atomTypes:
                msg  = "Could not find typename '%s' for atom '%s' in list of known atom types.\n" % (typename, str(atom))
                msg += "Known atom types are: %s" % str(self._atomTypes.keys())
                raise Exception(msg)

            # Add the particle to the OpenMM system.
            mass = self._atomTypes[typename].mass
            sys.addParticle(mass)

        # Adjust hydrogen masses if requested.
        if hydrogenMass is not None:
            if not u.is_quantity(hydrogenMass):
                hydrogenMass *= u.dalton
            for atom1, atom2 in topology.bonds():
                if atom1.element == elem.hydrogen:
                    (atom1, atom2) = (atom2, atom1)
                if atom2.element == elem.hydrogen and atom1.element not in (elem.hydrogen, None):
                    transfer_mass = hydrogenMass - sys.getParticleMass(atom2.index)
                    sys.setParticleMass(atom2.index, hydrogenMass)
                    mass = sys.getParticleMass(atom1.index) - transfer_mass
                    sys.setParticleMass(atom1.index, mass)

        # Set periodic boundary conditions.
        box_vectors = topology.getPeriodicBoxVectors()
        if box_vectors is not None:
            sys.setDefaultPeriodicBoxVectors(box_vectors[0],
                                             box_vectors[1],
                                             box_vectors[2])
        elif nonbondedMethod not in [NoCutoff, CutoffNonPeriodic]:
            raise ValueError('Requested periodic boundary conditions for a '
                             'Topology that does not specify periodic box '
                             'dimensions')

        # Make a list of all unique angles
        unique_angles = set()
        for bond in data.bonds:
            for atom in bonded_to_atom[bond.atom1]:
                if atom != bond.atom2:
                    if atom < bond.atom2:
                        unique_angles.add((atom, bond.atom1, bond.atom2))
                    else:
                        unique_angles.add((bond.atom2, bond.atom1, atom))
            for atom in bonded_to_atom[bond.atom2]:
                if atom != bond.atom1:
                    if atom > bond.atom1:
                        unique_angles.add((bond.atom1, bond.atom2, atom))
                    else:
                        unique_angles.add((atom, bond.atom2, bond.atom1))
        data.angles = sorted(list(unique_angles))

        # Make a list of all unique proper torsions
        unique_propers = set()
        for angle in data.angles:
            for atom in bonded_to_atom[angle[0]]:
                if atom not in angle:
                    if atom < angle[2]:
                        unique_propers.add((atom, angle[0], angle[1], angle[2]))
                    else:
                        unique_propers.add((angle[2], angle[1], angle[0], atom))
            for atom in bonded_to_atom[angle[2]]:
                if atom not in angle:
                    if atom > angle[0]:
                        unique_propers.add((angle[0], angle[1], angle[2], atom))
                    else:
                        unique_propers.add((atom, angle[2], angle[1], angle[0]))
        data.propers = sorted(list(unique_propers))

        # Make a list of all unique improper torsions
        for atom in range(len(bonded_to_atom)):
            bonded_to = bonded_to_atom[atom]
            if len(bonded_to) > 2:
                for subset in itertools.combinations(bonded_to, 3):
                    data.impropers.append((atom, subset[0], subset[1], subset[2]))

        # Identify bonds that should be implemented with constraints
        if constraints == AllBonds or constraints == HAngles:
            for bond in data.bonds:
                bond.isConstrained = True
        elif constraints == HBonds:
            for bond in data.bonds:
                atom1 = data.atoms[bond.atom1]
                atom2 = data.atoms[bond.atom2]
                bond.isConstrained = atom1.name.startswith('H') or atom2.name.startswith('H')
        if rigidWater:
            for bond in data.bonds:
                atom1 = data.atoms[bond.atom1]
                atom2 = data.atoms[bond.atom2]
                if atom1.residue.name == 'HOH' and atom2.residue.name == 'HOH':
                    bond.isConstrained = True

        # Identify angles that should be implemented with constraints
        if constraints == HAngles:
            for angle in data.angles:
                atom1 = data.atoms[angle[0]]
                atom2 = data.atoms[angle[1]]
                atom3 = data.atoms[angle[2]]
                numH = 0
                if atom1.name.startswith('H'):
                    numH += 1
                if atom3.name.startswith('H'):
                    numH += 1
                data.isAngleConstrained.append(numH == 2 or (numH == 1 and atom2.name.startswith('O')))
        else:
            data.isAngleConstrained = len(data.angles)*[False]
        if rigidWater:
            for i in range(len(data.angles)):
                angle = data.angles[i]
                atom1 = data.atoms[angle[0]]
                atom2 = data.atoms[angle[1]]
                atom3 = data.atoms[angle[2]]
                if atom1.residue.name == 'HOH' and atom2.residue.name == 'HOH' and atom3.residue.name == 'HOH':
                    data.isAngleConstrained[i] = True

        # Add virtual sites
        for atom in data.virtualSites:
            (site, atoms, excludeWith) = data.virtualSites[atom]
            index = atom.index
            data.excludeAtomWith[excludeWith].append(index)
            if site.type == 'average2':
                sys.setVirtualSite(index, mm.TwoParticleAverageSite(
                    atoms[0], atoms[1], site.weights[0], site.weights[1]))
            elif site.type == 'average3':
                sys.setVirtualSite(index, mm.ThreeParticleAverageSite(
                    atoms[0], atoms[1], atoms[2],
                    site.weights[0], site.weights[1], site.weights[2]))
            elif site.type == 'outOfPlane':
                sys.setVirtualSite(index, mm.OutOfPlaneSite(
                    atoms[0], atoms[1], atoms[2],
                    site.weights[0], site.weights[1], site.weights[2]))
            elif site.type == 'localCoords':
                local_coord_site = mm.LocalCoordinatesSite(
                    atoms[0], atoms[1], atoms[2],
                    mm.Vec3(site.originWeights[0], site.originWeights[1], site.originWeights[2]),
                    mm.Vec3(site.xWeights[0], site.xWeights[1], site.xWeights[2]),
                    mm.Vec3(site.yWeights[0], site.yWeights[1], site.yWeights[2]),
                    mm.Vec3(site.localPos[0], site.localPos[1], site.localPos[2]))
                sys.setVirtualSite(index, local_coord_site)

        # Add forces to the System
        for force in self._forces:
            force.createForce(sys, data, nonbondedMethod, nonbondedCutoff, args)
        if removeCMMotion:
            sys.addForce(mm.CMMotionRemover())

        # Let force generators do postprocessing
        for force in self._forces:
            if 'postprocessSystem' in dir(force):
                force.postprocessSystem(sys, data, args)

        # Execute scripts found in the XML files.
        for script in self._scripts:
            exec(script, locals())
        return sys
Example #18
0
def uff_C_3(atom):
    """ """
    return True


@Element('H')
@NeighborCount(1)
@NeighborsExactly('C', 1)
@Whitelist('H_')
def uff_H_(atom):
    """ """
    return True


if __name__ == "__main__":

    from foyer.atomtyper import find_atomtypes
    from foyer.forcefield import prepare_atoms

    from mbuild.examples.methane.methane import Methane

    m = Methane()
    # m = Ethane()

    traj = m.to_trajectory()
    prepare_atoms(traj.top)
    find_atomtypes(traj.top._atoms, forcefield='UFF')

    for atom in traj.top._atoms:
        print("Atom name={}, opls_type={}".format(atom.name, atom.atomtype))