Commit 98d053d4 authored by Robert McGibbon's avatar Robert McGibbon
Browse files

Improve docstrings

Swigged python docstrings now include documented return values and type
information or their arguments. They are generated in numpydoc format.
Furthermore, all of the Python app layer docstrings have been changed
to numpydoc format. The filterPythonFiles.py script which helps to
generate the Doxygen Python API docs has been updated to reflect these
changes.
parent 596a4197
......@@ -116,12 +116,8 @@ def _strip_optunit(thing, unit):
_resre = re.compile(r'(\d+)([a-zA-Z]*)')
class CharmmPsfFile(object):
"""
A chemical structure instantiated from CHARMM files.
"""A chemical structure instantiated from CHARMM files.
Example:
>>> cs = CharmmPsfFile("testfiles/test.psf")
This structure has numerous attributes that are lists of the elements of
this structure, including atoms, bonds, torsions, etc. The attributes are
- residue_list
......@@ -138,13 +134,14 @@ class CharmmPsfFile(object):
Additional attribute is available if a CharmmParameterSet is loaded into
this structure.
- urey_bradley_list
The lengths of each of these lists gives the pointers (e.g., natom, nres,
etc.)
Example:
Examples
--------
>>> cs = CharmmPsfFile("testfiles/test.psf")
>>> len(cs.atom_list)
33
......@@ -163,19 +160,21 @@ class CharmmPsfFile(object):
CMAP_FORCE_GROUP = 5
NONBONDED_FORCE_GROUP = 6
GB_FORCE_GROUP = 6
@_catchindexerror
def __init__(self, psf_name):
"""
Opens and parses a PSF file, then instantiates a CharmmPsfFile
"""Opens and parses a PSF file, then instantiates a CharmmPsfFile
instance from the data.
Parameters:
psf_name (str) : Name of the PSF file (it must exist)
Exceptions Raised:
IOError : If file "psf_name" does not exist
CharmmPSFError: If any parsing errors are encountered
Parameters
----------
psf_name : str
Name of the PSF file (it must exist)
Raises
------
IOError : If file "psf_name" does not exist
CharmmPSFError: If any parsing errors are encountered
"""
conv = CharmmPsfFile._convert
# Make sure the file exists
......@@ -388,14 +387,17 @@ class CharmmPsfFile(object):
@staticmethod
def _convert(string, type, message):
"""
Converts a string to a specific type, making sure to raise
"""Converts a string to a specific type, making sure to raise
CharmmPSFError with the given message in the event of a failure.
Parameters:
- string (str) : Input string to process
- type (type) : Type of data to convert to
- message (str) : Error message to put in exception if failed
Parameters
----------
string : str
Input string to process
type : type
Type of data to convert to
message : str
Error message to put in exception if failed
"""
try:
return type(string)
......@@ -405,23 +407,24 @@ class CharmmPsfFile(object):
@staticmethod
def _parse_psf_section(psf):
"""
This method parses a section of the PSF file
Parameters:
- psf (CharmmFile) : Open file that is pointing to the first line
of the section that is to be parsed
Returns:
(title, pointers, data)
- title (str) : The label of the PSF section we are parsing
- pointers (int/tuple of ints) : If one pointer is set, pointers is
simply the integer that is value of that pointer. Otherwise
it is a tuple with every pointer value defined in the first
line
- data (list) : A list of all data in the parsed section converted
to `dtype'
"""This method parses a section of the PSF file
Parameters
----------
psf : CharmmFile
Open file that is pointing to the first line of the section
that is to be parsed
Returns
--------
title : str
The label of the PSF section we are parsing
pointers : int/tuple of ints
If one pointer is set, pointers is simply the integer that is
value of that pointer. Otherwise it is a tuple with every pointer
value defined in the first line
data : list
A list of all data in the parsed section converted to `dtype'
"""
conv = CharmmPsfFile._convert
line = psf.readline()
......@@ -462,25 +465,25 @@ class CharmmPsfFile(object):
return title, pointers, data
def loadParameters(self, parmset):
"""
Loads parameters from a parameter set that was loaded via CHARMM RTF,
"""Loads parameters from a parameter set that was loaded via CHARMM RTF,
PAR, and STR files.
Parameters:
- parmset (CharmmParameterSet) : List of all parameters
Notes:
- If any parameters that are necessary cannot be found, a
MissingParameter exception is raised.
- If any dihedral or improper parameters cannot be found, I will try
inserting wildcards (at either end for dihedrals and as the two
central atoms in impropers) and see if that matches. Wild-cards
will apply ONLY if specific parameters cannot be found.
- This method will expand the dihedral_parameter_list attribute by
adding a separate Dihedral object for each term for types that
have a multi-term expansion
Parameters
----------
parmset : CharmmParameterSet
List of all parameters
Notes
-----
- If any parameters that are necessary cannot be found, a
MissingParameter exception is raised.
- If any dihedral or improper parameters cannot be found, I will try
inserting wildcards (at either end for dihedrals and as the two
central atoms in impropers) and see if that matches. Wild-cards
will apply ONLY if specific parameters cannot be found.
- This method will expand the dihedral_parameter_list attribute by
adding a separate Dihedral object for each term for types that
have a multi-term expansion
"""
# First load the atom types
types_are_int = False
......@@ -620,7 +623,7 @@ class CharmmPsfFile(object):
pass
# Cache the topology for easy returning later
self._topology = topology = Topology()
last_chain = None
last_residue = None
# Add each chain (separate 'system's) and residue
......@@ -752,52 +755,60 @@ class CharmmPsfFile(object):
ewaldErrorTolerance=0.0005,
flexibleConstraints=True,
verbose=False):
"""
Construct an OpenMM System representing the topology described by the
"""Construct an OpenMM System representing the topology described by the
prmtop file. You MUST have loaded a parameter set into this PSF before
calling createSystem. If not, AttributeError will be raised. ValueError
is raised for illegal input.
Parameters:
- params (CharmmParameterSet) The parameter set to use to parametrize
this molecule
- 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.
- switchDistance (distance=0*nanometer) The distance at which the
switching function is active for nonbonded interactions. If the
switchDistance evaluates to boolean False (if it is 0), no
switching function will be used. Illegal values will raise a
ValueError
- constraints (object=None) Specifies which bonds or 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
- implicitSolvent (object=None) If not None, the implicit solvent
model to use. Allowed values are HCT, OBC1, OBC2, or GBn
- implicitSolventKappa (float=None): Debye screening parameter to
model salt concentrations in GB solvent.
- implicitSolventSaltConc (float=0.0*u.moles/u.liter): Salt
concentration for GB simulations. Converted to Debye length
`kappa'
- temperature (float=298.15*u.kelvin): Temperature used in the salt
concentration-to-kappa conversion for GB salt concentration term
- soluteDielectric (float=1.0) The solute dielectric constant to use
in the implicit solvent model.
- solventDielectric (float=78.5) The solvent dielectric constant to
use in the implicit solvent model.
- 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.
- ewaldErrorTolerance (float=0.0005) The error tolerance to use if the
nonbonded method is Ewald or PME.
- flexibleConstraints (bool=True) Are our constraints flexible or not?
- verbose (bool=False) Optionally prints out a running progress report
Parameters
----------
params : CharmmParameterSet
The parameter set to use to parametrize this molecule
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.
switchDistance : distance=0*nanometer
The distance at which the switching function is active for nonbonded
interactions. If the switchDistance evaluates to boolean False (if
it is 0), no switching function will be used. Illegal values will
raise a ValueError
constraints : object=None
Specifies which bonds or 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
implicitSolvent : object=None
If not None, the implicit solvent model to use. Allowed values are
HCT, OBC1, OBC2, or GBn
implicitSolventKappa : float=None
Debye screening parameter to model salt concentrations in GB
solvent.
implicitSolventSaltConc : float=0.0*u.moles/u.liter
Salt concentration for GB simulations. Converted to Debye length
`kappa'
temperature : float=298.15*u.kelvin
Temperature used in the salt concentration-to-kappa conversion for
GB salt concentration term
soluteDielectric : float=1.0
The solute dielectric constant to use in the implicit solvent model.
solventDielectric : float=78.5
The solvent dielectric constant to use in the implicit solvent
model.
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.
ewaldErrorTolerance : float=0.0005
The error tolerance to use if the nonbonded method is Ewald or PME.
flexibleConstraints : bool=True
Are our constraints flexible or not?
verbose : bool=False
Optionally prints out a running progress report
"""
# Load the parameter set
self.loadParameters(params.condense())
......@@ -821,7 +832,7 @@ class CharmmPsfFile(object):
raise ValueError('Illegal implicit solvent model choice.')
if not constraints in (None, ff.HAngles, ff.HBonds, ff.AllBonds):
raise ValueError('Illegal constraints choice')
# Define conversion factors
length_conv = u.angstrom.conversion_factor_to(u.nanometer)
_chmfrc = u.kilocalorie_per_mole/(u.angstrom*u.angstrom)
......@@ -833,7 +844,7 @@ class CharmmPsfFile(object):
dihe_frc_conv = u.kilocalorie_per_mole.conversion_factor_to(
u.kilojoule_per_mole)
ene_conv = dihe_frc_conv
# Create the system and determine if any of our atoms have NBFIX (and
# therefore requires a CustomNonbondedForce instead)
typenames = set()
......@@ -1358,7 +1369,7 @@ class CharmmPsfFile(object):
def boxLengths(self, stuff):
raise RuntimeError('Use setBox to set a box with lengths and angles '
'or set the boxVectors attribute with box vectors')
@property
def boxVectors(self):
""" Return the box vectors """
......@@ -1403,12 +1414,12 @@ def set_molecules(atom_list):
owner = []
# The way I do this is via a recursive algorithm, in which
# the "set_owner" method is called for each bonded partner an atom
# has, which in turn calls set_owner for each of its partners and
# has, which in turn calls set_owner for each of its partners and
# so on until everything has been assigned.
molecule_number = 1 # which molecule number we are on
for i in range(len(atom_list)):
# If this atom has not yet been "owned", make it the next molecule
# However, we only increment which molecule number we're on if
# However, we only increment which molecule number we're on if
# we actually assigned a new molecule (obviously)
if not atom_list[i].marked:
tmp = [i]
......@@ -1429,7 +1440,7 @@ def _set_owner(atom_list, owner_array, atm, mol_id):
owner_array.append(partner.idx)
_set_owner(atom_list, owner_array, partner.idx, mol_id)
elif partner.marked != mol_id:
raise MoleculeError('Atom %d in multiple molecules' %
raise MoleculeError('Atom %d in multiple molecules' %
partner.idx)
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
......
......@@ -8,7 +8,7 @@ Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2014 Stanford University and the Authors.
Authors: Robert McGibbon
Contributors:
Contributors:
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
......@@ -71,10 +71,12 @@ class CheckpointReporter(object):
def __init__(self, file, reportInterval):
"""Create a CheckpointReporter.
Parameters:
- file (string or open file object) The file to write to. Any current
contents will be overwritten.
- reportInterval (int) The interval (in time steps) at which to write checkpoints
Parameters
----------
file : string or open file object
The file to write to. Any current contents will be overwritten.
reportInterval : int
The interval (in time steps) at which to write checkpoints.
"""
self._reportInterval = reportInterval
......@@ -88,12 +90,23 @@ class CheckpointReporter(object):
def describeNextReport(self, simulation):
"""Get information about the next report this object will generate.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
Returns: A five element tuple. The first element is the number of steps until the
next report. The remaining elements specify whether that report will require
positions, velocities, forces, and energies respectively.
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
Returns
-------
int
The number of steps until the
bool
Requires positions
bool
Requires velocities
bool
Requires forces
bool
Requires energies
"""
steps = self._reportInterval - simulation.currentStep%self._reportInterval
return (steps, False, False, False, False)
......@@ -101,9 +114,12 @@ class CheckpointReporter(object):
def report(self, simulation, state):
"""Generate a report.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
- state (State) The current state of the simulation
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
state : State
The current state of the simulation
"""
self._out.seek(0)
chk = simulation.context.createCheckpoint()
......
......@@ -55,12 +55,19 @@ class DCDFile(object):
def __init__(self, file, topology, dt, firstStep=0, interval=1):
"""Create a DCD file and write out the header.
Parameters:
- file (file) A file to write to
- topology (Topology) The Topology defining the molecular system being written
- dt (time) The time step used in the trajectory
- firstStep (int=0) The index of the first step in the trajectory
- interval (int=1) The frequency (measured in time steps) at which states are written to the trajectory
Parameters
----------
file : file
A file to write to
topology : Topology
The Topology defining the molecular system being written
dt : time
The time step used in the trajectory
firstStep : int=0
The index of the first step in the trajectory
interval : int=1
The frequency (measured in time steps) at which states are written
to the trajectory
"""
self._file = file
self._topology = topology
......@@ -83,14 +90,21 @@ class DCDFile(object):
def writeModel(self, positions, unitCellDimensions=None, periodicBoxVectors=None):
"""Write out a model to the DCD file.
The periodic box can be specified either by the unit cell dimensions (for a rectangular box), or the full set of box
vectors (for an arbitrary triclinic box). If neither is specified, the box vectors specified in the Topology will be
used. Regardless of the value specified, no dimensions will be written if the Topology does not represent a periodic system.
Parameters:
- positions (list) The list of atomic positions to write
- unitCellDimensions (Vec3=None) The dimensions of the crystallographic unit cell.
- periodicBoxVectors (tuple of Vec3=None) The vectors defining the periodic box.
The periodic box can be specified either by the unit cell dimensions
(for a rectangular box), or the full set of box vectors (for an
arbitrary triclinic box). If neither is specified, the box vectors
specified in the Topology will be used. Regardless of the value
specified, no dimensions will be written if the Topology does not
represent a periodic system.
Parameters
----------
positions : list
The list of atomic positions to write
unitCellDimensions : Vec3=None
The dimensions of the crystallographic unit cell.
periodicBoxVectors : tuple of Vec3=None
The vectors defining the periodic box.
"""
if len(list(self._topology.atoms())) != len(positions):
raise ValueError('The number of positions must match the number of atoms')
......
......@@ -56,11 +56,23 @@ class DCDReporter(object):
def describeNextReport(self, simulation):
"""Get information about the next report this object will generate.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
Returns: A five element tuple. The first element is the number of steps until the
next report. The remaining elements specify whether that report will require
positions, velocities, forces, and energies respectively.
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
Returns
-------
int
The number of steps until the
bool
Requires positions
bool
Requires velocities
bool
Requires forces
bool
Requires energies
"""
steps = self._reportInterval - simulation.currentStep%self._reportInterval
return (steps, True, False, False, False)
......@@ -68,10 +80,14 @@ class DCDReporter(object):
def report(self, simulation, state):
"""Generate a report.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
- state (State) The current state of the simulation
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
state : State
The current state of the simulation
"""
if self._dcd is None:
self._dcd = DCDFile(self._out, simulation.topology, simulation.integrator.getStepSize(), 0, self._reportInterval)
a,b,c = state.getPeriodicBoxVectors()
......
......@@ -157,16 +157,24 @@ class DesmondDMSFile(object):
def createSystem(self, nonbondedMethod=ff.NoCutoff, nonbondedCutoff=1.0*nanometer,
ewaldErrorTolerance=0.0005, removeCMMotion=True, hydrogenMass=None):
"""Construct an OpenMM System representing the topology described by this dms file
Parameters:
- 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
- ewaldErrorTolerance (float=0.0005) The error tolerance to use if nonbondedMethod is Ewald or PME.
- 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.
"""Construct an OpenMM System representing the topology described by this
DMS file
Parameters
----------
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
ewaldErrorTolerance : float=0.0005
The error tolerance to use if nonbondedMethod is Ewald or PME.
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.
"""
self._checkForUnsupportedTerms()
sys = mm.System()
......
......@@ -123,12 +123,14 @@ class ForceField(object):
def loadFile(self, file):
"""Load an XML file and add the definitions from it to this FieldField.
Parameters:
- file (string or file) An XML file containing force field definitions. It may
be either an absolute file path, a path relative to the current working
directory, a path relative to this module's data subdirectory
(for built in force fields), or an open file-like object with a
read() method from which the forcefield XML data can be loaded.
Parameters
----------
file : string or file
An XML file containing force field definitions. It may be either an
absolute file path, a path relative to the current working
directory, a path relative to this module's data subdirectory (for
built in force fields), or an open file-like object with a read()
method from which the forcefield XML data can be loaded.
"""
try:
# this handles either filenames or open file-like objects
......
......@@ -183,10 +183,14 @@ class GromacsGroFile(object):
def getPositions(self, asNumpy=False, frame=0):
"""Get the atomic positions.
Parameters:
- asNumpy (boolean=False) if true, the values are returned as a numpy array instead of a list of Vec3s
- frame (int=0) the index of the frame for which to get positions
"""
Parameters
----------
asNumpy : boolean=False
if true, the values are returned as a numpy array instead of a list
of Vec3s
frame : int=0
the index of the frame for which to get positions
"""
if asNumpy:
if self._numpyPositions is None:
self._numpyPositions = [None]*len(self._positions)
......@@ -198,16 +202,20 @@ class GromacsGroFile(object):
def getPeriodicBoxVectors(self, frame=0):
"""Get the vectors defining the periodic box.
Parameters:
- frame (int=0) the index of the frame for which to get the box vectors
Parameters
----------
frame : int=0
the index of the frame for which to get the box vectors
"""
return self._periodicBoxVectors[frame]
def getUnitCellDimensions(self, frame=0):
"""Get the dimensions of the crystallographic unit cell.
Parameters:
- frame (int=0) the index of the frame for which to get the unit cell dimensions
Parameters
----------
frame : int=0
the index of the frame for which to get the unit cell dimensions
"""
xsize = self._periodicBoxVectors[frame][0][0].value_in_unit(nanometers)
ysize = self._periodicBoxVectors[frame][1][1].value_in_unit(nanometers)
......
......@@ -539,23 +539,42 @@ class GromacsTopFile(object):
def createSystem(self, nonbondedMethod=ff.NoCutoff, nonbondedCutoff=1.0*unit.nanometer,
constraints=None, rigidWater=True, implicitSolvent=None, soluteDielectric=1.0, solventDielectric=78.5, ewaldErrorTolerance=0.0005, removeCMMotion=True, hydrogenMass=None):
"""Construct an OpenMM System representing the topology described by this prmtop file.
Parameters:
- 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
- implicitSolvent (object=None) If not None, the implicit solvent model to use. The only allowed value is OBC2.
- soluteDielectric (float=1.0) The solute dielectric constant to use in the implicit solvent model.
- solventDielectric (float=78.5) The solvent dielectric constant to use in the implicit solvent model.
- ewaldErrorTolerance (float=0.0005) The error tolerance to use if nonbondedMethod is Ewald or PME.
- 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.
Returns: the newly created System
"""Construct an OpenMM System representing the topology described by this
prmtop file.
Parameters
----------
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
implicitSolvent : object=None
If not None, the implicit solvent model to use. The only allowed
value is OBC2.
soluteDielectric : float=1.0
The solute dielectric constant to use in the implicit solvent model.
solventDielectric : float=78.5
The solvent dielectric constant to use in the implicit solvent
model.
ewaldErrorTolerance : float=0.0005
The error tolerance to use if nonbondedMethod is Ewald or PME.
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.
Returns
-------
the newly created System
"""
# Create the System.
......@@ -586,9 +605,9 @@ class GromacsTopFile(object):
topologyAtoms = list(self.topology.atoms())
exceptions = []
fudgeQQ = float(self._defaults[4])
# Build a lookup table to let us process dihedrals more quickly.
dihedralTypeTable = {}
for key in self._dihedralTypes:
if key[1] != 'X' and key[2] != 'X':
......@@ -837,7 +856,7 @@ class GromacsTopFile(object):
for atom in atoms[1:]:
if atom > atoms[0]:
exceptions.append((baseAtomIndex+atoms[0], baseAtomIndex+atom, 0, 0, 0))
# Create nonbonded exceptions.
......@@ -855,9 +874,9 @@ class GromacsTopFile(object):
nb.setNonbondedMethod(methodMap[nonbondedMethod])
nb.setCutoffDistance(nonbondedCutoff)
nb.setEwaldErrorTolerance(ewaldErrorTolerance)
# Adjust masses.
if hydrogenMass is not None:
for atom1, atom2 in self.topology.bonds():
if atom1.element == elem.hydrogen:
......
......@@ -85,12 +85,16 @@ class Modeller(object):
def add(self, addTopology, addPositions):
"""Add chains, residues, atoms, and bonds to the model.
Specify what to add by providing a new Topology object and the corresponding atomic positions.
All chains, residues, atoms, and bonds contained in the Topology are added to the model.
Parameters:
- addTopoology (Topology) a Topology whose contents should be added to the model
- addPositions (list) the positions of the atoms to add
Specify what to add by providing a new Topology object and the
corresponding atomic positions. All chains, residues, atoms, and bonds
contained in the Topology are added to the model.
Parameters
----------
addTopology : Topology
a Topology whose contents should be added to the model
addPositions : list
the positions of the atoms to add
"""
# Copy over the existing model.
......@@ -137,8 +141,11 @@ class Modeller(object):
You also can specify a bond (as a tuple of Atom objects) to delete just that bond without
deleting the Atoms it connects.
Parameters:
- toDelete (list) a list of Atoms, Residues, Chains, and bonds (specified as tuples of Atoms) to delete
Parameters
----------
toDelete : list
a list of Atoms, Residues, Chains, and bonds (specified as tuples of
Atoms) to delete
"""
newTopology = Topology()
newTopology.setPeriodicBoxVectors(self.topology.getPeriodicBoxVectors())
......@@ -178,7 +185,7 @@ class Modeller(object):
Parameters:
- model (string='tip3p') the water model to convert to. Supported values are 'tip3p', 'spce', 'tip4pew', and 'tip5p'.
@deprecated Use addExtraParticles() instead. It performs the same function but in a more general way.
"""
if model in ('tip3p', 'spce'):
......@@ -252,7 +259,7 @@ class Modeller(object):
4. Ion pairs are added to give the requested total ionic strength.
The box size can be specified in any of several ways:
1. You can explicitly give the vectors defining the periodic box to use.
2. Alternatively, for a rectangular box you can simply give the dimensions of the unit cell.
3. You can give a padding distance. The largest dimension of the solute (along the x, y, or z axis) is determined, and a cubic
......@@ -294,13 +301,13 @@ class Modeller(object):
pdbTopology = pdb.getTopology()
pdbPositions = pdb.getPositions().value_in_unit(nanometer)
pdbResidues = list(pdbTopology.residues())
pdbBoxSize = pdbTopology.getUnitCellDimensions().value_in_unit(nanometer)
pdbBoxSize = pdbTopology.getUnitCellDimensions().value_in_unit(nanometer)
# Pick a unit cell size.
if numAdded is not None:
# Select a padding distance which is guaranteed to give more than the specified number of molecules.
padding = 1.1*(numAdded/((len(pdbResidues)/pdbBoxSize[0]**3)*8))**(1.0/3.0)
if padding < 0.5:
padding = 0.5 # Ensure we have enough when adding very small numbers of molecules
......@@ -442,20 +449,20 @@ class Modeller(object):
if numAdded is not None:
# We added many more waters than we actually want. Sort them based on distance to the nearest box edge and
# only keep the ones in the middle.
lowerBound = center-box/2
upperBound = center+box/2
distToEdge = (min(min(pos-lowerBound), min(upperBound-pos)) for index, pos in addedWaters)
sortedIndex = [i[0] for i in sorted(enumerate(distToEdge), key=lambda x: -x[1])]
addedWaters = [addedWaters[i] for i in sortedIndex[:numAdded]]
# Compute a new periodic box size.
maxSize = max(max((pos[i] for index, pos in addedWaters))-min((pos[i] for index, pos in addedWaters)) for i in range(3))
newTopology.setUnitCellDimensions(Vec3(maxSize, maxSize, maxSize))
else:
# There could be clashes between water molecules at the box edges. Find ones to remove.
upperCutoff = center+box/2-Vec3(waterCutoff, waterCutoff, waterCutoff)
lowerCutoff = center-box/2+Vec3(waterCutoff, waterCutoff, waterCutoff)
lowerSkinPositions = [pos for index, pos in addedWaters if pos[0] < lowerCutoff[0] or pos[1] < lowerCutoff[1] or pos[2] < lowerCutoff[2]]
......@@ -604,16 +611,28 @@ class Modeller(object):
Definitions for standard amino acids and nucleotides are built in. You can call loadHydrogenDefinitions() to load
additional definitions for other residue types.
Parameters:
- forcefield (ForceField=None) the ForceField to use for determining the positions of hydrogens. If this is None,
positions will be picked which are generally reasonable but not optimized for any particular ForceField.
- pH (float=7.0) the pH based on which to select variants
- variants (list=None) an optional list of variants to use. If this is specified, its length must equal the number
of residues in the model. variants[i] is the name of the variant to use for residue i (indexed starting at 0).
If an element is None, the standard rules will be followed to select a variant for that residue.
- platform (Platform=None) the Platform to use when computing the hydrogen atom positions. If this is None,
the default Platform will be used.
Returns: a list of what variant was actually selected for each residue, in the same format as the variants parameter
Parameters
----------
forcefield : ForceField=None
the ForceField to use for determining the positions of hydrogens.
If this is None, positions will be picked which are generally
reasonable but not optimized for any particular ForceField.
pH : float=7.0
the pH based on which to select variants
variants : list=None
an optional list of variants to use. If this is specified, its
length must equal the number of residues in the model. variants[i]
is the name of the variant to use for residue i (indexed starting at
0). If an element is None, the standard rules will be followed to
select a variant for that residue.
platform : Platform=None
the Platform to use when computing the hydrogen atom positions. If
this is None, the default Platform will be used.
Returns
-------
a list of what variant was actually selected for each residue,
in the same format as the variants param
"""
# Check the list of variants.
......@@ -802,7 +821,7 @@ class Modeller(object):
if forcefield is not None:
# Use the ForceField the user specified.
system = forcefield.createSystem(newTopology, rigidWater=False)
atoms = list(newTopology.atoms())
for i in range(system.getNumParticles()):
......@@ -812,7 +831,7 @@ class Modeller(object):
else:
# Create a System that restrains the distance of each hydrogen from its parent atom
# and causes hydrogens to spread out evenly.
system = System()
nonbonded = CustomNonbondedForce('100/((r/0.1)^4+1)')
bonds = HarmonicBondForce()
......@@ -836,7 +855,7 @@ class Modeller(object):
for residue in newTopology.residues():
if residue.name == 'HOH':
# Add an angle term to make the water geometry correct.
atoms = list(residue.atoms())
oindex = [i for i in range(len(atoms)) if atoms[i].element == elem.oxygen]
if len(atoms) == 3 and len(oindex) == 1:
......@@ -844,12 +863,12 @@ class Modeller(object):
angles.addAngle(atoms[hindex[0]].index, atoms[oindex[0]].index, atoms[hindex[1]].index, 1.824, 836.8)
else:
# Add angle terms for any hydroxyls.
for atom in residue.atoms():
index = atom.index
if atom.element == elem.oxygen and len(bondedTo[index]) == 2 and elem.hydrogen in (a.element for a in bondedTo[index]):
angles.addAngle(bondedTo[index][0].index, index, bondedTo[index][1].index, 1.894, 460.24)
if platform is None:
context = Context(system, VerletIntegrator(0.0))
else:
......@@ -862,18 +881,24 @@ class Modeller(object):
return actualVariants
def addExtraParticles(self, forcefield):
"""Add missing extra particles to the model that are required by a force field.
Some force fields use "extra particles" that do not represent actual atoms, but still need to be included in
the System. Examples include lone pairs, Drude particles, and the virtual sites used in some water models
to adjust the charge distribution. Extra particles can be recognized by the fact that their element is None.
This method is primarily used to add extra particles, but it can also remove them. It tries to match every
residue in the Topology to a template in the force field. If there is no match, it will both add and remove
extra particles as necessary to make it match.
Parameters:
- forcefield (ForceField) the ForceField defining what extra particles should be present
"""Add missing extra particles to the model that are required by a force
field.
Some force fields use "extra particles" that do not represent
actual atoms, but still need to be included in the System. Examples
include lone pairs, Drude particles, and the virtual sites used in some
water models to adjust the charge distribution. Extra particles can be
recognized by the fact that their element is None.
This method is primarily used to add extra particles, but it can also
remove them. It tries to match every residue in the Topology to a
template in the force field. If there is no match, it will both add
and remove extra particles as necessary to make it match.
Parameters
----------
forcefield : ForceField
the ForceField defining what extra particles should be present
"""
# Create copies of all residue templates that have had all extra points removed.
......
......@@ -176,10 +176,14 @@ class PDBFile(object):
def getPositions(self, asNumpy=False, frame=0):
"""Get the atomic positions.
Parameters:
- asNumpy (boolean=False) if true, the values are returned as a numpy array instead of a list of Vec3s
- frame (int=0) the index of the frame for which to get positions
"""
Parameters
----------
asNumpy : boolean=False
if true, the values are returned as a numpy array instead of a list
of Vec3s
frame : int=0
the index of the frame for which to get positions
"""
if asNumpy:
if self._numpyPositions is None:
self._numpyPositions = [None]*len(self._positions)
......@@ -234,13 +238,19 @@ class PDBFile(object):
def writeFile(topology, positions, file=sys.stdout, keepIds=False):
"""Write a PDB file containing a single model.
Parameters:
- topology (Topology) The Topology defining the model to write
- positions (list) The list of atomic positions to write
- file (file=stdout) A file to write to
- keepIds (bool=False) If True, keep the residue and chain IDs specified in the Topology rather than generating
new ones. Warning: It is up to the caller to make sure these are valid IDs that satisfy the requirements of
the PDB format. Otherwise, the output file will be invalid.
Parameters
----------
topology : Topology
The Topology defining the model to write
positions : list
The list of atomic positions to write
file : file=stdout
A file to write to
keepIds : bool=False
If True, keep the residue and chain IDs specified in the Topology
rather than generating new ones. Warning: It is up to the caller to
make sure these are valid IDs that satisfy the requirements of the
PDB format. Otherwise, the output file will be invalid.
"""
PDBFile.writeHeader(topology, file)
PDBFile.writeModel(topology, positions, file, keepIds=keepIds)
......@@ -250,9 +260,12 @@ class PDBFile(object):
def writeHeader(topology, file=sys.stdout):
"""Write out the header for a PDB file.
Parameters:
- topology (Topology) The Topology defining the molecular system being written
- file (file=stdout) A file to write the file to
Parameters
----------
topology : Topology
The Topology defining the molecular system being written
file : file=stdout
A file to write the file to
"""
print("REMARK 1 CREATED WITH OPENMM %s, %s" % (Platform.getOpenMMVersion(), str(date.today())), file=file)
vectors = topology.getPeriodicBoxVectors()
......@@ -266,15 +279,24 @@ class PDBFile(object):
def writeModel(topology, positions, file=sys.stdout, modelIndex=None, keepIds=False):
"""Write out a model to a PDB file.
Parameters:
- topology (Topology) The Topology defining the model to write
- positions (list) The list of atomic positions to write
- file (file=stdout) A file to write the model to
- modelIndex (int=None) If not None, the model will be surrounded by MODEL/ENDMDL records with this index
- keepIds (bool=False) If True, keep the residue and chain IDs specified in the Topology rather than generating
new ones. Warning: It is up to the caller to make sure these are valid IDs that satisfy the requirements of
the PDB format. Otherwise, the output file will be invalid.
Parameters
----------
topology : Topology
The Topology defining the model to write
positions : list
The list of atomic positions to write
file : file=stdout
A file to write the model to
modelIndex : int=None
If not None, the model will be surrounded by MODEL/ENDMDL records
with this index
keepIds : bool=False
If True, keep the residue and chain IDs specified in the Topology
rather than generating new ones. Warning: It is up to the caller to
make sure these are valid IDs that satisfy the requirements of the
PDB format. Otherwise, the output file will be invalid.
"""
if len(list(topology.atoms())) != len(positions):
raise ValueError('The number of positions must match the number of atoms')
if is_quantity(positions):
......@@ -331,12 +353,15 @@ class PDBFile(object):
def writeFooter(topology, file=sys.stdout):
"""Write out the footer for a PDB file.
Parameters:
- topology (Topology) The Topology defining the molecular system being written
- file (file=stdout) A file to write the file to
Parameters
----------
topology : Topology
The Topology defining the molecular system being written
file : file=stdout
A file to write the file to
"""
# Identify bonds that should be listed as CONECT records.
standardResidues = ['ALA', 'ASN', 'CYS', 'GLU', 'HIS', 'LEU', 'MET', 'PRO', 'THR', 'TYR',
'ARG', 'ASP', 'GLN', 'GLY', 'ILE', 'LYS', 'PHE', 'SER', 'TRP', 'VAL',
'A', 'G', 'C', 'U', 'I', 'DA', 'DG', 'DC', 'DT', 'DI', 'HOH']
......@@ -347,9 +372,9 @@ class PDBFile(object):
elif atom1.name == 'SG' and atom2.name == 'SG' and atom1.residue.name == 'CYS' and atom2.residue.name == 'CYS':
conectBonds.append((atom1, atom2))
if len(conectBonds) > 0:
# Work out the index used in the PDB file for each atom.
atomIndex = {}
nextAtomIndex = 0
prevChain = None
......@@ -360,9 +385,9 @@ class PDBFile(object):
prevChain = atom.residue.chain
atomIndex[atom] = nextAtomIndex
nextAtomIndex += 1
# Record which other atoms each atom is bonded to.
atomBonds = {}
for atom1, atom2 in conectBonds:
index1 = atomIndex[atom1]
......@@ -373,9 +398,9 @@ class PDBFile(object):
atomBonds[index2] = []
atomBonds[index1].append(index2)
atomBonds[index2].append(index1)
# Write the CONECT records.
for index1 in sorted(atomBonds):
bonded = atomBonds[index1]
while len(bonded) > 4:
......
......@@ -56,11 +56,23 @@ class PDBReporter(object):
def describeNextReport(self, simulation):
"""Get information about the next report this object will generate.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
Returns: A five element tuple. The first element is the number of steps until the
next report. The remaining elements specify whether that report will require
positions, velocities, forces, and energies respectively.
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
Returns
-------
int
The number of steps until the
bool
Requires positions
bool
Requires velocities
bool
Requires forces
bool
Requires energies
"""
steps = self._reportInterval - simulation.currentStep%self._reportInterval
return (steps, True, False, False, False)
......@@ -68,9 +80,12 @@ class PDBReporter(object):
def report(self, simulation, state):
"""Generate a report.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
- state (State) The current state of the simulation
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
state : State
The current state of the simulation
"""
if self._nextModel == 0:
PDBFile.writeHeader(simulation.topology, self._out)
......@@ -95,9 +110,12 @@ class PDBxReporter(PDBReporter):
def report(self, simulation, state):
"""Generate a report.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
- state (State) The current state of the simulation
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
state : State
The current state of the simulation
"""
if self._nextModel == 0:
PDBxFile.writeHeader(simulation.topology, self._out)
......
......@@ -193,10 +193,14 @@ class PDBxFile(object):
def getPositions(self, asNumpy=False, frame=0):
"""Get the atomic positions.
Parameters:
- asNumpy (boolean=False) if true, the values are returned as a numpy array instead of a list of Vec3s
- frame (int=0) the index of the frame for which to get positions
"""
Parameters
----------
asNumpy : bool=False
if true, the values are returned as a numpy array instead of a list
of Vec3s
frame : int=0
the index of the frame for which to get positions
"""
if asNumpy:
if self._numpyPositions is None:
self._numpyPositions = [None]*len(self._positions)
......@@ -210,14 +214,21 @@ class PDBxFile(object):
entry=None):
"""Write a PDBx/mmCIF file containing a single model.
Parameters:
- topology (Topology) The Topology defining the model to write
- positions (list) The list of atomic positions to write
- file (file=stdout) A file to write to
- keepIds (bool=False) If True, keep the residue and chain IDs specified in the Topology rather than generating
new ones. Warning: It is up to the caller to make sure these are valid IDs that satisfy the requirements of
the PDBx/mmCIF format. Otherwise, the output file will be invalid.
- entry (str=None) The entry ID to assign to the CIF file
Parameters
----------
topology : Topology
The Topology defining the model to write
positions : list
The list of atomic positions to write
file : file=stdout
A file to write to
keepIds : bool=False
If True, keep the residue and chain IDs specified in the Topology
rather than generating new ones. Warning: It is up to the caller to
make sure these are valid IDs that satisfy the requirements of the
PDBx/mmCIF format. Otherwise, the output file will be invalid.
entry : str=None
The entry ID to assign to the CIF file
"""
PDBxFile.writeHeader(topology, file, entry)
PDBxFile.writeModel(topology, positions, file, keepIds=keepIds)
......@@ -226,10 +237,14 @@ class PDBxFile(object):
def writeHeader(topology, file=sys.stdout, entry=None):
"""Write out the header for a PDBx/mmCIF file.
Parameters:
- topology (Topology) The Topology defining the molecular system being written
- file (file=stdout) A file to write the file to
- entry (str=None) The entry ID to assign to the CIF file
Parameters
----------
topology : Topology
The Topology defining the molecular system being written
file : file=stdout
A file to write the file to
entry : str=None
The entry ID to assign to the CIF file
"""
if entry is not None:
print('data_%s' % entry, file=file)
......@@ -280,14 +295,21 @@ class PDBxFile(object):
def writeModel(topology, positions, file=sys.stdout, modelIndex=1, keepIds=False):
"""Write out a model to a PDBx/mmCIF file.
Parameters:
- topology (Topology) The Topology defining the model to write
- positions (list) The list of atomic positions to write
- file (file=stdout) A file to write the model to
- modelIndex (int=1) The model number of this frame
- keepIds (bool=False) If True, keep the residue and chain IDs specified in the Topology rather than generating
new ones. Warning: It is up to the caller to make sure these are valid IDs that satisfy the requirements of
the PDBx/mmCIF format. Otherwise, the output file will be invalid.
Parameters
----------
topology : Topology
The Topology defining the model to write
positions : list
The list of atomic positions to write
file : file=stdout
A file to write the model to
modelIndex : int=1
The model number of this frame
keepIds : bool=False
If True, keep the residue and chain IDs specified in the Topology
rather than generating new ones. Warning: It is up to the caller to
make sure these are valid IDs that satisfy the requirements of the
PDBx/mmCIF format. Otherwise, the output file will be invalid.
"""
if len(list(topology.atoms())) != len(positions):
raise ValueError('The number of positions must match the number of atoms')
......
......@@ -84,35 +84,48 @@ class Simulation(object):
def minimizeEnergy(self, tolerance=10*unit.kilojoule/unit.mole, maxIterations=0):
"""Perform a local energy minimization on the system.
Parameters:
- tolerance (energy=10*kilojoules/mole) The energy tolerance to which the system should be minimized
- maxIterations (int=0) The maximum number of iterations to perform. If this is 0, minimization is continued
until the results converge without regard to how many iterations it takes.
Parameters
----------
tolerance : energy=10*kilojoules/mole
The energy tolerance to which the system should be minimized
maxIterations : int=0
The maximum number of iterations to perform. If this is 0,
minimization is continued until the results converge without regard
to how many iterations it takes.
"""
mm.LocalEnergyMinimizer.minimize(self.context, tolerance, maxIterations)
def step(self, steps):
"""Advance the simulation by integrating a specified number of time steps."""
self._simulate(endStep=self.currentStep+steps)
def runForClockTime(self, time, checkpointFile=None, stateFile=None, checkpointInterval=None):
"""Advance the simulation by integrating time steps until a fixed amount of clock time has elapsed.
This is useful when you have a limited amount of computer time available, and want to run the longest simulation
possible in that time. This method will continue taking time steps until the specified clock time has elapsed,
then return. It also can automatically write out a checkpoint and/or state file before returning, so you can
later resume the simulation. Another option allows it to write checkpoints or states at regular intervals, so
you can resume even if the simulation is interrupted before the time limit is reached.
Parameters:
- time (time) the amount of time to run for. If no units are specified, it is assumed to be a number of hours.
- checkpointFile (string or file=None) if specified, a checkpoint file will be written at the end of the
simulation (and optionally at regular intervals before then) by passing this to saveCheckpoint().
- stateFile (string or file=None) if specified, a state file will be written at the end of the
simulation (and optionally at regular intervals before then) by passing this to saveState().
- checkpointInterval (time=None) if specified, checkpoints and/or states will be written at regular intervals
during the simulation, in addition to writing a final version at the end. If no units are specified, this is
assumed to be in hours.
Parameters
----------
time : time
the amount of time to run for. If no units are specified, it is
assumed to be a number of hours.
checkpointFile : string or file=None
if specified, a checkpoint file will be written at the end of the
simulation (and optionally at regular intervals before then) by
passing this to saveCheckpoint().
stateFile : string or file=None
if specified, a state file will be written at the end of the
simulation (and optionally at regular intervals before then) by
passing this to saveState().
checkpointInterval : time=None
if specified, checkpoints and/or states will be written at regular
intervals during the simulation, in addition to writing a final
version at the end. If no units are specified, this is assumed to
be in hours.
"""
if unit.is_quantity(time):
time = time.value_in_unit(unit.hours)
......@@ -131,7 +144,7 @@ class Simulation(object):
self.saveCheckpoint(checkpointFile)
if stateFile is not None:
self.saveState(stateFile)
def _simulate(self, endStep=None, endTime=None):
if endStep is None:
endStep = sys.maxsize
......@@ -174,30 +187,36 @@ class Simulation(object):
def saveCheckpoint(self, file):
"""Save a checkpoint of the simulation to a file.
The output is a binary file that contains a complete representation of the current state of the Simulation.
It includes both publicly visible data such as the particle positions and velocities, and also internal data
such as the states of random number generators. Reloading the checkpoint will put the Simulation back into
precisely the same state it had before, so it can be exactly continued.
A checkpoint file is highly specific to the Simulation it was created from. It can only be loaded into
another Simulation that has an identical System, uses the same Platform and OpenMM version, and is running on
identical hardware. If you need a more portable way to resume simulations, consider using saveState() instead.
Parameters:
- file (string or file) a File-like object to write the checkpoint to, or alternatively a filename
Parameters
----------
file : string or file
a File-like object to write the checkpoint to, or alternatively a
filename
"""
if isinstance(file, str):
with open(file, 'wb') as f:
f.write(self.context.createCheckpoint())
else:
file.write(self.context.createCheckpoint())
def loadCheckpoint(self, file):
"""Load a checkpoint file that was created with saveCheckpoint().
Parameters:
- file (string or file) a File-like object to load the checkpoint from, or alternatively a filename
Parameters
----------
file : string or file
a File-like object to load the checkpoint from, or alternatively a
filename
"""
if isinstance(file, str):
with open(file, 'rb') as f:
......@@ -207,18 +226,21 @@ class Simulation(object):
def saveState(self, file):
"""Save the current state of the simulation to a file.
The output is an XML file containing a serialized State object. It includes all publicly visible data,
including positions, velocities, and parameters. Reloading the State will put the Simulation back into
approximately the same state it had before.
Unlike saveCheckpoint(), this does not store internal data such as the states of random number generators.
Therefore, you should not expect the following trajectory to be identical to what would have been produced
with the original Simulation. On the other hand, this means it is portable across different Platforms or
hardware.
Parameters:
- file (string or file) a File-like object to write the state to, or alternatively a filename
Parameters
----------
file : string or file
a File-like object to write the state to, or alternatively a
filename
"""
state = self.context.getState(getPositions=True, getVelocities=True, getParameters=True)
xml = mm.XmlSerializer.serialize(state)
......@@ -227,12 +249,15 @@ class Simulation(object):
f.write(xml)
else:
file.write(xml)
def loadState(self, file):
"""Load a State file that was created with saveState().
Parameters:
- file (string or file) a File-like object to load the state from, or alternatively a filename
Parameters
----------
file : string or file
a File-like object to load the state from, or alternatively a
filename
"""
if isinstance(file, str):
with open(file, 'r') as f:
......
......@@ -129,11 +129,23 @@ class StateDataReporter(object):
def describeNextReport(self, simulation):
"""Get information about the next report this object will generate.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
Returns: A five element tuple. The first element is the number of steps until the
next report. The remaining elements specify whether that report will require
positions, velocities, forces, and energies respectively.
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
Returns
-------
int
The number of steps until the
bool
Requires positions
bool
Requires velocities
bool
Requires forces
bool
Requires energies
"""
steps = self._reportInterval - simulation.currentStep%self._reportInterval
return (steps, self._needsPositions, self._needsVelocities, self._needsForces, self._needEnergy)
......@@ -141,9 +153,12 @@ class StateDataReporter(object):
def report(self, simulation, state):
"""Generate a report.
Parameters:
- simulation (Simulation) The Simulation to generate a report for
- state (State) The current state of the simulation
Parameters
----------
simulation : Simulation
The Simulation to generate a report for
state : State
The current state of the simulation
"""
if not self._hasInitialized:
self._initializeConstants(simulation)
......
......@@ -54,9 +54,12 @@ class Unit(object):
def __init__(self, base_or_scaled_units):
"""Create a new Unit.
Parameters:
- self (Unit) The newly created Unit.
- base_or_scaled_units (dict) Keys are BaseUnits or ScaledUnits. Values are exponents (numbers).
Parameters
----------
self : Unit
The newly created Unit.
base_or_scaled_units : dict
Keys are BaseUnits or ScaledUnits. Values are exponents (numbers).
"""
# Unit contents are of two types: BaseUnits and ScaledUnits
self._top_base_units = {}
......@@ -389,7 +392,8 @@ class Unit(object):
Strips off any ScaledUnits in the Unit, leaving only BaseUnits.
Parameters
- system: a dictionary of (BaseDimension, BaseUnit) pairs
----------
system : a dictionary of (BaseDimension, BaseUnit) pairs
"""
return system.express_unit(self)
......@@ -583,7 +587,7 @@ class UnitSystem(object):
Parameters
----------
units: ``list``
units : list
List of base units from which to construct the unit system
"""
def __init__(self, units):
......@@ -678,7 +682,7 @@ def is_unit(x):
Returns True if x is a Unit, False otherwise.
Examples
--------
>>> is_unit(16)
False
"""
......
......@@ -45,7 +45,7 @@ using namespace OpenMM;
%}
%feature("autodoc", "1");
%feature("autodoc", "0");
%nodefaultctor;
%include features.i
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment