Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docstrings, run in CI #240

Merged
merged 4 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ jobs:

working-directory: ./charmm

- name: Run docstrings
if: ${{ matrix.latest-openff-toolkit == true }}
continue-on-error: True
run: |
pytest --doctest-modules openmmforcefields --ignore=openmmforcefields/tests

- name: Upload coverage report to CodeCov
uses: codecov/[email protected]
if: ${{ github.repository == 'openmm/openmmforcefields'
Expand Down
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ If you're not familiar with this approach to applying parameters to biomolecular

### Using the AMBER force fields

Once installed, the AMBER force fields will be registered in the `amber/` relative path searched by [`simtk.openmm.app.ForceField`](http://docs.openmm.org/latest/api-python/generated/simtk.openmm.app.forcefield.ForceField.html#simtk.openmm.app.forcefield.ForceField).
Once installed, the AMBER force fields will be registered in the `amber/` relative path searched by [`openmm.app.ForceField`](http://docs.openmm.org/latest/api-python/generated/openmm.app.forcefield.ForceField.html#openmm.app.forcefield.ForceField).

For example, to specify the newer recommended [`ff14SB`](https://pubs.acs.org/doi/abs/10.1021/acs.jctc.5b00255) force field and accompanying recommended ions and solvent models (corresponding to force fields loaded in LEaP with `leaprc.protein.ff14SB`), prepend the `amber` prefix and the `.xml` suffix:
```python
Expand Down Expand Up @@ -67,7 +67,7 @@ forcefield = ForceField('charmm/toppar_all36_prot_model.xml')

## Using AMBER GAFF 1.x and 2.x for small molecules

The `openmmforcefields` package includes a [residue template generator](http://docs.openmm.org/latest/userguide/application.html#adding-residue-template-generators) for [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/simtk.openmm.app.forcefield.ForceField.html#simtk.openmm.app.forcefield.ForceField) that automatically generates OpenMM residue templates for small molecules lacking parameters using [GAFF](http://ambermd.org/antechamber/gaff.html) versions 1 or 2.
The `openmmforcefields` package includes a [residue template generator](http://docs.openmm.org/latest/userguide/application.html#adding-residue-template-generators) for [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/openmm.app.forcefield.ForceField.html#openmm.app.forcefield.ForceField) that automatically generates OpenMM residue templates for small molecules lacking parameters using [GAFF](http://ambermd.org/antechamber/gaff.html) versions 1 or 2.

### Cheminformatics toolkits

Expand All @@ -78,7 +78,7 @@ The OpenEye toolkit is available [for free for academics for non-IP-generating a
### On-the-fly template generation for small molecules

Generation of OpenMM-compatible parameters for small molecules encountered in an OpenMM `Topology` is handled through `openmmforcefields.generators.GAFFTemplateGenerator`.
Because the [OpenMM `Topology` object](http://docs.openmm.org/latest/api-python/generated/simtk.openmm.app.topology.Topology.html#simtk.openmm.app.topology.Topology) used by [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/simtk.openmm.app.forcefield.ForceField.html#simtk.openmm.app.forcefield.ForceField) does not know the precise chemical identity of molecules represented in the topology---which contain only elements and bonds between them, without stereochemical or bond order information---it is necessary to instruct `GAFFTemplateGenerator` which small molecules it will encounter in processing the `Topology` object ahead of time; it then matches these by element and bond pattern.
Because the [OpenMM `Topology` object](http://docs.openmm.org/latest/api-python/generated/openmm.app.topology.Topology.html#openmm.app.topology.Topology) used by [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/openmm.app.forcefield.ForceField.html#openmm.app.forcefield.ForceField) does not know the precise chemical identity of molecules represented in the topology---which contain only elements and bonds between them, without stereochemical or bond order information---it is necessary to instruct `GAFFTemplateGenerator` which small molecules it will encounter in processing the `Topology` object ahead of time; it then matches these by element and bond pattern.

### Specifying molecules

Expand Down Expand Up @@ -112,14 +112,14 @@ molecule = Molecule.from_smiles('c1ccccc1')
from openmmforcefields.generators import GAFFTemplateGenerator
gaff = GAFFTemplateGenerator(molecules=molecule)
# Create an OpenMM ForceField object with AMBER ff14SB and TIP3P with compatible ions
from simtk.openmm.app import ForceField
from openmm.app import ForceField
forcefield = ForceField('amber/protein.ff14SB.xml', 'amber/tip3p_standard.xml', 'amber/tip3p_HFE_multivalent.xml')
# Register the GAFF template generator
forcefield.registerTemplateGenerator(gaff.generator)
# You can now parameterize an OpenMM Topology object that contains the specified molecule.
# forcefield will load the appropriate GAFF parameters when needed, and antechamber
# will be used to generate small molecule parameters on the fly.
from simtk.openmm.app import PDBFile
from openmm.app import PDBFile
pdbfile = PDBFile('t4-lysozyme-L99A-with-benzene.pdb')
system = forcefield.createSystem(pdbfile.topology)
```
Expand Down Expand Up @@ -152,7 +152,7 @@ Newly parameterized molecules will be written to the cache, saving time next tim

## Using the Open Force Field Initiative SMIRNOFF small molecule force fields

The `openmmforcefields` package includes a [residue template generator](http://docs.openmm.org/latest/userguide/application.html#adding-residue-template-generators) for [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/simtk.openmm.app.forcefield.ForceField.html#simtk.openmm.app.forcefield.ForceField) that automatically generates OpenMM residue templates for small molecules lacking parameters using the [Open Force Field Initiative](http://openforcefield.org) [SMIRNOFF](https://open-forcefield-toolkit.readthedocs.io/en/0.6.0/smirnoff.html) small molecule force fields.
The `openmmforcefields` package includes a [residue template generator](http://docs.openmm.org/latest/userguide/application.html#adding-residue-template-generators) for [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/openmm.app.forcefield.ForceField.html#openmm.app.forcefield.ForceField) that automatically generates OpenMM residue templates for small molecules lacking parameters using the [Open Force Field Initiative](http://openforcefield.org) [SMIRNOFF](https://open-forcefield-toolkit.readthedocs.io/en/0.6.0/smirnoff.html) small molecule force fields.
This includes the [`openff-1.0.0` ("Parsley")](https://openforcefield.org/news/introducing-openforcefield-1.0/) small molecule force field, as well as [newer versions of this force field](https://github.com/openforcefield/openff-forcefields).

The `SMIRNOFFTemplateGenerator` residue template generator operates in a manner very similar to `GAFFTemplateGenerator`, so we only highlight its differences here.
Expand All @@ -168,7 +168,7 @@ molecule = Molecule.from_smiles('c1ccccc1')
from openmmforcefields.generators import SMIRNOFFTemplateGenerator
smirnoff = SMIRNOFFTemplateGenerator(molecules=molecule)
# Create an OpenMM ForceField object with AMBER ff14SB and TIP3P with compatible ions
from simtk.openmm.app import ForceField
from openmm.app import ForceField
forcefield = ForceField('amber/protein.ff14SB.xml', 'amber/tip3p_standard.xml', 'amber/tip3p_HFE_multivalent.xml')
# Register the SMIRNOFF template generator
forcefield.registerTemplateGenerator(smirnoff.generator)
Expand Down Expand Up @@ -210,7 +210,7 @@ Newly parameterized molecules will be written to the cache, saving time next tim

## Using espaloma to generate small molecule force fields

The `openmmforcefields` package includes a [residue template generator](http://docs.openmm.org/latest/userguide/application.html#adding-residue-template-generators) for [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/simtk.openmm.app.forcefield.ForceField.html#simtk.openmm.app.forcefield.ForceField) that can automatically generate OpenMM residue templates for small molecules lacking parameters using [espaloma](https://github.com/choderalab/espaloma) via one of its released force fields, provided `espaloma` and its dependencies are installed.
The `openmmforcefields` package includes a [residue template generator](http://docs.openmm.org/latest/userguide/application.html#adding-residue-template-generators) for [the OpenMM `ForceField` class](http://docs.openmm.org/latest/api-python/generated/openmm.app.forcefield.ForceField.html#openmm.app.forcefield.ForceField) that can automatically generate OpenMM residue templates for small molecules lacking parameters using [espaloma](https://github.com/choderalab/espaloma) via one of its released force fields, provided `espaloma` and its dependencies are installed.
`espaloma` uses a [graph convolutional model](https://arxiv.org/abs/2010.01196) to generate both valence parameters and fast partial charges.

The `EspalomaTemplateGenerator` residue template generator operates in a manner very similar to `GAFFTemplateGenerator`, so we only highlight its differences here.
Expand All @@ -228,7 +228,7 @@ molecule = Molecule.from_smiles('c1ccccc1')
from openmmforcefields.generators import EspalomaTemplateGenerator
espaloma = EspalomaTemplateGenerator(molecules=molecule, forcefield='espaloma-0.2.2')
# Create an OpenMM ForceField object with AMBER ff14SB and TIP3P with compatible ions
from simtk.openmm.app import ForceField
from openmm.app import ForceField
forcefield = ForceField('amber/protein.ff14SB.xml', 'amber/tip3p_standard.xml', 'amber/tip3p_HFE_multivalent.xml')
# Register the SMIRNOFF template generator
forcefield.registerTemplateGenerator(espaloma.generator)
Expand Down Expand Up @@ -264,8 +264,8 @@ The `openmmforcefields` package provides the `openmmforcefields.generators.Syste
Here's an example that uses GAFF 2.11 along with the new `ff14SB` generation of AMBER force fields (and compatible solvent models) to generate an OpenMM `System` object from an [Open Force Field `Topology`](https://open-forcefield-toolkit.readthedocs.io/en/latest/api/generated/openff.toolkit.topology.Topology.html#openff.toolkit.topology.Topology) object:
```python
# Define the keyword arguments to feed to ForceField
from simtk import unit
from simtk.openmm import app
from openmm import unit
from openmm import app
forcefield_kwargs = { 'constraints' : app.HBonds, 'rigidWater' : True, 'removeCMMotion' : False, 'hydrogenMass' : 4*unit.amu }
# Initialize a SystemGenerator using GAFF
from openmmforcefields.generators import SystemGenerator
Expand All @@ -282,7 +282,7 @@ Parameters for multiple force fields can be held in the same cache file.
By default, `SystemGenerator` will use `PME` for periodic systems and `NoCutoff` for non-periodic systems.
You can modify this behavior with the optional `periodic_forcefield_kwargs` and `nonperiodic_forcefield_kwargs` arguments, which are used to update `forcefield_kwargs` depending on whether the system is periodic or non-periodic:
```python
from simtk.openmm import app
from openmm import app
system_generator = SystemGenerator(forcefields=['amber/ff14SB.xml', 'amber/tip3p_standard.xml'],
periodic_forcefield_kwargs={'nonbondedMethod' : app.LJPME},
nonperiodic_forcefield_kwargs={'nonbondedMethod' : app.CutoffNonPeriodic})
Expand Down
5 changes: 3 additions & 2 deletions charmm/energy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
from __future__ import print_function
import sys
import parmed as pmd
from simtk import openmm as mm, unit as u
from simtk.openmm import app
import openmm as mm
from openmm import unit as u
from openmm import app
import numpy as np
import time
import os, re
Expand Down
18 changes: 9 additions & 9 deletions charmm/test_charmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from collections import OrderedDict
import hashlib
import os
import simtk.openmm.app as app
import simtk.openmm as mm
import simtk.unit as u
import openmm.app as app
import openmm as mm
import openmm.unit as u
import argparse
import csv
import logging
Expand Down Expand Up @@ -100,7 +100,7 @@ def write_serialized_system(filename, system):
----------
filename : str
The name of the file to be written
system : simtk.openmm.System
system : openmm.System
The System object to be written

"""
Expand Down Expand Up @@ -129,7 +129,7 @@ def read_box_vectors(filename):

Returns
-------
box_vectors : simtk.unit.Quantity with shape [3,3] and units of Angstroms
box_vectors : openmm.unit.Quantity with shape [3,3] and units of Angstroms
Box vectors
"""
with open(filename, 'r') as infile:
Expand Down Expand Up @@ -162,14 +162,14 @@ def compute_potential(system, positions):

Parameters
----------
system : simtk.openmm.System
system : openmm.System
System
positions : simtk.unit.Quantity of shape [nparticles,3] with units compatible with angstroms
positions : openmm.unit.Quantity of shape [nparticles,3] with units compatible with angstroms
Positions

Returns
-------
potential : simtk.unit.Quantity with units of kJ/mol
potential : openmm.unit.Quantity with units of kJ/mol
The potential energy

"""
Expand Down Expand Up @@ -202,7 +202,7 @@ def compare_energies(system_name, pdb_filename, psf_filename, ffxml_filenames, t
Keyword arguments to pass to CharmmPsfFile.createSystem() and ForceField.CreateSystem() when constructing System objects for energy comparison
tolerance : float, optional, default=1e-5
Relative energy discrepancy tolerance
units : simtk.unit.Unit
units : openmm.unit.Unit
Unit to use for energy comparison
write_serialized_xml : bool, optional, default=False
If True, will write out serialized System XML files for OpenMM systems to aid debugging.
Expand Down
9 changes: 7 additions & 2 deletions openmmforcefields/generators/system_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,22 @@ def __init__(self, forcefields=None, small_molecule_forcefield='openff-1.0.0', f
If the ``cache`` argument is specified, parameterized molecules are cached in the corresponding file.

>>> cache = 'db.json'
>>> system_generator = SystemGenerator(forcefields=forcefields, small_molecule_forcefield='gaff-2.11', forcefield_kwargs=forcefield_kwargs, cache=cache)
>>> system_generator = SystemGenerator(forcefields=amber_forcefields, small_molecule_forcefield='gaff-2.11', forcefield_kwargs=forcefield_kwargs, cache=cache) # doctest: +SKIP

To use a barostat, you need to define a barostat whose parameters will be copied into each system (with a different random number seed):

>>> import openmm
>>> from openmm import unit
>>> pressure = 1.0 * unit.atmospheres
>>> temperature = 298.0 * unit.kelvin
>>> frequency = 25 # steps
>>> system_generator.barostat = openmm.MonteCarloBarostat(pressure, temperature, frequency)

Now, you can create an OpenMM ``System`` object from an OpenMM ``Topology`` object and a list of OpenFF ``Molecule`` objects

>>> from openff.toolkit import Molecule, Topology
>>> molecules = [Molecule.from_smiles(smiles) for smiles in ["CCO", "c1ccccc1"]]
>>> openmm_topology = Topology.from_molecules(molecules).to_openmm()
>>> system = system_generator.create_system(openmm_topology, molecules=molecules)

Parameters for multiple force fields can be held in the same cache file.
Expand All @@ -145,7 +150,7 @@ def __init__(self, forcefields=None, small_molecule_forcefield='openff-1.0.0', f
simply change the ``small_molecule_forcefield`` parameter to one of the supported ``GAFFTemplateGenerator.INSTALLED_FORCEFIELDS``:

>>> small_molecule_forcefield = 'openff-1.0.0'
>>> system_generator = SystemGenerator(forcefields=forcefields, small_molecule_forcefield=small_molecule_forcefield, forcefield_kwargs=forcefield_kwargs)
>>> system_generator = SystemGenerator(forcefields=amber_forcefields, small_molecule_forcefield=small_molecule_forcefield, forcefield_kwargs=forcefield_kwargs)

For debugging convenience, you can also turn _off_ specific interactions during system creation, such as particle charges:

Expand Down
Loading