Commit cf8a03e8 authored by peastman's avatar peastman
Browse files

Merged changes from main branch

parents f7f70136 31d02cdc
...@@ -116,6 +116,8 @@ class PDBFile(object): ...@@ -116,6 +116,8 @@ class PDBFile(object):
element = elem.lithium element = elem.lithium
elif upper.startswith('K'): elif upper.startswith('K'):
element = elem.potassium element = elem.potassium
elif upper.startswith('ZN'):
element = elem.zinc
elif( len( residue ) == 1 and upper.startswith('CA') ): elif( len( residue ) == 1 and upper.startswith('CA') ):
element = elem.calcium element = elem.calcium
else: else:
......
...@@ -36,6 +36,7 @@ import gzip ...@@ -36,6 +36,7 @@ import gzip
import simtk.openmm as mm import simtk.openmm as mm
import simtk.unit as unit import simtk.unit as unit
import math import math
import time
class StateDataReporter(object): class StateDataReporter(object):
"""StateDataReporter outputs information about a simulation, such as energy and temperature, to a file. """StateDataReporter outputs information about a simulation, such as energy and temperature, to a file.
...@@ -45,7 +46,8 @@ class StateDataReporter(object): ...@@ -45,7 +46,8 @@ class StateDataReporter(object):
written in comma-separated-value (CSV) format, but you can specify a different separator to use. written in comma-separated-value (CSV) format, but you can specify a different separator to use.
""" """
def __init__(self, file, reportInterval, step=False, time=False, potentialEnergy=False, kineticEnergy=False, totalEnergy=False, temperature=False, volume=False, density=False, separator=',', systemMass=None): def __init__(self, file, reportInterval, step=False, time=False, potentialEnergy=False, kineticEnergy=False, totalEnergy=False, temperature=False, volume=False, density=False,
progress=False, remainingTime=False, speed=False, separator=',', systemMass=None, totalSteps=None):
"""Create a StateDataReporter. """Create a StateDataReporter.
Parameters: Parameters:
...@@ -59,14 +61,24 @@ class StateDataReporter(object): ...@@ -59,14 +61,24 @@ class StateDataReporter(object):
- temperature (boolean=False) Whether to write the instantaneous temperature to the file - temperature (boolean=False) Whether to write the instantaneous temperature to the file
- volume (boolean=False) Whether to write the periodic box volume to the file - volume (boolean=False) Whether to write the periodic box volume to the file
- density (boolean=False) Whether to write the system density to the file - density (boolean=False) Whether to write the system density to the file
- progress (boolean=False) Whether to write current progress (percent completion) to the file.
If this is True, you must also specify totalSteps.
- remainingTime (boolean=False) Whether to write an estimate of the remaining clock time until
completion to the file. If this is True, you must also specify totalSteps.
- speed (bool=False) Whether to write an estimate of the simulation speed in ns/day to the file
- separator (string=',') The separator to use between columns in the file - separator (string=',') The separator to use between columns in the file
- systemMass (mass=None) The total mass to use for the system when reporting density. If this is - systemMass (mass=None) The total mass to use for the system when reporting density. If this is
None (the default), the system mass is computed by summing the masses of all particles. This None (the default), the system mass is computed by summing the masses of all particles. This
parameter is useful when the particle masses do not reflect their actual physical mass, such as parameter is useful when the particle masses do not reflect their actual physical mass, such as
when some particles have had their masses set to 0 to immobilize them. when some particles have had their masses set to 0 to immobilize them.
- totalSteps (int=None) The total number of steps that will be included in the simulation. This
is required if either progress or remainingTime is set to True, and defines how many steps will
indicate 100% completion.
""" """
self._reportInterval = reportInterval self._reportInterval = reportInterval
self._openedFile = isinstance(file, str) self._openedFile = isinstance(file, str)
if (progress or remainingTime) and totalSteps is None:
raise ValueError('Reporting progress or remaining time requires total steps to be specified')
if self._openedFile: if self._openedFile:
# Detect the desired compression scheme from the filename extension # Detect the desired compression scheme from the filename extension
# and open all files unbuffered # and open all files unbuffered
...@@ -86,8 +98,12 @@ class StateDataReporter(object): ...@@ -86,8 +98,12 @@ class StateDataReporter(object):
self._temperature = temperature self._temperature = temperature
self._volume = volume self._volume = volume
self._density = density self._density = density
self._progress = progress
self._remainingTime = remainingTime
self._speed = speed
self._separator = separator self._separator = separator
self._totalMass = systemMass self._totalMass = systemMass
self._totalSteps = totalSteps
self._hasInitialized = False self._hasInitialized = False
self._needsPositions = False self._needsPositions = False
self._needsVelocities = False self._needsVelocities = False
...@@ -121,6 +137,9 @@ class StateDataReporter(object): ...@@ -121,6 +137,9 @@ class StateDataReporter(object):
self._out.flush() self._out.flush()
except AttributeError: except AttributeError:
pass pass
self._initialClockTime = time.time()
self._initialSimulationTime = state.getTime()
self._initialSteps = simulation.currentStep
self._hasInitialized = True self._hasInitialized = True
# Check for errors. # Check for errors.
...@@ -150,6 +169,9 @@ class StateDataReporter(object): ...@@ -150,6 +169,9 @@ class StateDataReporter(object):
values = [] values = []
box = state.getPeriodicBoxVectors() box = state.getPeriodicBoxVectors()
volume = box[0][0]*box[1][1]*box[2][2] volume = box[0][0]*box[1][1]*box[2][2]
clockTime = time.time()
if self._progress:
values.append('%.1f%%' % (100.0*simulation.currentStep/self._totalSteps))
if self._step: if self._step:
values.append(simulation.currentStep) values.append(simulation.currentStep)
if self._time: if self._time:
...@@ -166,6 +188,33 @@ class StateDataReporter(object): ...@@ -166,6 +188,33 @@ class StateDataReporter(object):
values.append(volume.value_in_unit(unit.nanometer**3)) values.append(volume.value_in_unit(unit.nanometer**3))
if self._density: if self._density:
values.append((self._totalMass/volume).value_in_unit(unit.gram/unit.item/unit.milliliter)) values.append((self._totalMass/volume).value_in_unit(unit.gram/unit.item/unit.milliliter))
if self._speed:
elapsedDays = (clockTime-self._initialClockTime)/86400
elapsedNs = (state.getTime()-self._initialSimulationTime).value_in_unit(unit.nanosecond)
values.append('%.3g' % (elapsedNs/elapsedDays))
if self._remainingTime:
elapsedSeconds = clockTime-self._initialClockTime
elapsedSteps = simulation.currentStep-self._initialSteps
if elapsedSteps == 0:
value = '--'
else:
estimatedTotalSeconds = (self._totalSteps-self._initialSteps)*elapsedSeconds/elapsedSteps
remainingSeconds = int(estimatedTotalSeconds-elapsedSeconds)
remainingDays = remainingSeconds//86400
remainingSeconds -= remainingDays*86400
remainingHours = remainingSeconds//3600
remainingSeconds -= remainingHours*3600
remainingMinutes = remainingSeconds//60
remainingSeconds -= remainingMinutes*60
if remainingDays > 0:
value = "%d:%d:%02d:%02d" % (remainingDays, remainingHours, remainingMinutes, remainingSeconds)
elif remainingHours > 0:
value = "%d:%02d:%02d" % (remainingHours, remainingMinutes, remainingSeconds)
elif remainingMinutes > 0:
value = "%d:%02d" % (remainingMinutes, remainingSeconds)
else:
value = "0:%02d" % remainingSeconds
values.append(value)
return values return values
def _initializeConstants(self, simulation): def _initializeConstants(self, simulation):
...@@ -200,6 +249,8 @@ class StateDataReporter(object): ...@@ -200,6 +249,8 @@ class StateDataReporter(object):
Returns: a list of strings giving the title of each observable being reported on. Returns: a list of strings giving the title of each observable being reported on.
""" """
headers = [] headers = []
if self._progress:
headers.append('Progress (%)')
if self._step: if self._step:
headers.append('Step') headers.append('Step')
if self._time: if self._time:
...@@ -216,6 +267,10 @@ class StateDataReporter(object): ...@@ -216,6 +267,10 @@ class StateDataReporter(object):
headers.append('Box Volume (nm^3)') headers.append('Box Volume (nm^3)')
if self._density: if self._density:
headers.append('Density (g/mL)') headers.append('Density (g/mL)')
if self._speed:
headers.append('Speed (ns/day)')
if self._remainingTime:
headers.append('Time Remaining')
return headers return headers
def _checkForErrors(self, simulation, state): def _checkForErrors(self, simulation, state):
......
...@@ -135,9 +135,10 @@ class SwigInputBuilder: ...@@ -135,9 +135,10 @@ class SwigInputBuilder:
# Read all the XML files and merge them into a single document. # Read all the XML files and merge them into a single document.
self.doc = etree.ElementTree(etree.Element('root')) self.doc = etree.ElementTree(etree.Element('root'))
for file in os.listdir(inputDirname): for file in os.listdir(inputDirname):
root = etree.parse(os.path.join(inputDirname, file)).getroot() if file.lower().endswith('xml'):
for node in root: root = etree.parse(os.path.join(inputDirname, file)).getroot()
self.doc.getroot().append(node) for node in root:
self.doc.getroot().append(node)
if outputFilename: if outputFilename:
self.fOut = open(outputFilename, 'w') self.fOut = open(outputFilename, 'w')
......
...@@ -136,6 +136,10 @@ NO_OUTPUT_ARGS = [('LocalEnergyMinimizer', 'minimize', 'context'), ...@@ -136,6 +136,10 @@ NO_OUTPUT_ARGS = [('LocalEnergyMinimizer', 'minimize', 'context'),
STEAL_OWNERSHIP = {("Platform", "registerPlatform") : [0], STEAL_OWNERSHIP = {("Platform", "registerPlatform") : [0],
("System", "addForce") : [0], ("System", "addForce") : [0],
("System", "setVirtualSite") : [1], ("System", "setVirtualSite") : [1],
("CustomNonbondedForce", "addTabulatedFunction") : [1],
("CustomGBForce", "addTabulatedFunction") : [1],
("CustomHbondForce", "addTabulatedFunction") : [1],
("CustomCompoundBondForce", "addTabulatedFunction") : [1],
} }
# This is a list of units to attach to return values and method args. # This is a list of units to attach to return values and method args.
...@@ -179,6 +183,7 @@ UNITS = { ...@@ -179,6 +183,7 @@ UNITS = {
("*", "getSolventDielectric") : (None, ()), ("*", "getSolventDielectric") : (None, ()),
("*", "getStepSize") : ("unit.picosecond", ()), ("*", "getStepSize") : ("unit.picosecond", ()),
("*", "getSystem") : (None, ()), ("*", "getSystem") : (None, ()),
("*", "getTabulatedFunction") : (None, ()),
("*", "getUseDispersionCorrection") : (None, ()), ("*", "getUseDispersionCorrection") : (None, ()),
("*", "getTemperature") : ("unit.kelvin", ()), ("*", "getTemperature") : ("unit.kelvin", ()),
("*", "getUseDispersionCorrection") : (None, ()), ("*", "getUseDispersionCorrection") : (None, ()),
......
...@@ -219,19 +219,21 @@ class State(_object): ...@@ -219,19 +219,21 @@ class State(_object):
# Strings can cause trouble # Strings can cause trouble
# as can any container that has infinite levels of containment # as can any container that has infinite levels of containment
def _is_string(x): def _is_string(x):
# step 1) String is always a container # step 1) String is always a container
# and its contents are themselves containers. # and its contents are themselves containers.
try: try:
first_item = iter(x).next() first_item = iter(x).next()
inner_item = iter(first_item).next() inner_item = iter(first_item).next()
if first_item == inner_item: if first_item == inner_item:
return True return True
else: else:
return False return False
except TypeError: except TypeError:
return False return False
except StopIteration: except StopIteration:
return False return False
except ValueError:
return False
def stripUnits(args): def stripUnits(args):
""" """
......
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