Commit 25da3061 authored by Jason Swails's avatar Jason Swails
Browse files

First pass at adding my CHARMM compatibility layer.

Currently gives exactly the same energy as the same files passed through chamber
(which, in turn, was validated to machine precision against CHARMM itself).
parent e213f51c
"""
This package contains code for reading CHARMM structure files for setting up a
simulation with CHARMM; specifically PSF, PAR, RTF, and STR files
- PAR : Parameter file (PRM) -- this contains all of the force field
parameters (e.g., bond lengths and strengths) for all of the atom
types
- RTF : Residue Topology File -- this file contains the residue
connectivity tables as well as a definition of all of the atom
types. Also contains an internal coordinate representation of the
residues
- PSF : Protein Structure File -- this is the main file type in CHARMM
simulations that defines all of the residues in a system as well as
the atom types and connectivity between the atoms
- STR : Stream file -- Source of additional information and CHARMM commands
that can contain RTF and PAR information. Allows users to define
additional parameters without 'contaminating' the original force
field parameter files
"""
__all__ = ['psf', 'parameters', 'openmmloader']
__authors__ = 'Jason Swails'
__contributors__ = ''
__license__ = 'GPL v.3'
__date__ = 'Mar. 31, 2014'
__private__ = ['topologyobjects', '_charmmfile']
"""
Provides a class for reading CHARMM-style files. The key component to these
files is that the ! character is a comment character and everything after ! is
ignored.
Author: Jason M. Swails
Contributors:
Date: April 9, 2014
"""
from simtk.openmm.app.charmm.exceptions import CharmmFileError
class CharmmFile(object):
"""
A CHARMM file that recognizes the "!" character as a 'comment' token. It
can be iterated over and generally treated like a file object, but only
spits out strings that have been truncated at its first comment character.
There is currently no way to recognize a ! as a _non_ comment character,
since allowing an escape character does not seem to be common practice and
would likely introduce negative performance implications.
"""
def __init__(self, fname, mode='r'):
if mode not in ('r', 'w'):
raise ValueError('Cannot open CharmmFile with mode "%s"' % mode)
if mode == 'r':
self.status = 'OLD'
else:
self.status = 'NEW'
try:
self._handle = open(fname, mode)
except IOError, e:
raise CharmmFileError(str(e))
self.closed = False
self.line_number = 0
def write(self, *args, **kwargs):
return self._handle.write(*args, **kwargs)
def __iter__(self):
# Iterate over the file
for line in self._handle:
try:
idx = line.index('!')
end = '\n'
except ValueError:
# There is no comment...
idx = None
end = ''
yield line[:idx] + end
def readline(self):
self.line_number += 1
line = self._handle.readline()
try:
idx = line.index('!')
end = '\n'
except ValueError:
idx = None
end = ''
return line[:idx] + end
def readlines(self):
return [line for line in self]
def read(self):
return ''.join(self.readlines())
def close(self):
self._handle.close()
self.closed = True
def rewind(self):
""" Return to the beginning of the file """
self._handle.seek(0)
def __del__(self):
self.closed or self._handle.close()
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class CharmmStreamFile(object):
"""
The stream file is broken down into sections of commands delimited by the
strings:
read <section> <options>
....
....
end
This object provides iterators over those sections and a file-like API for
dealing with the text.
"""
def __init__(self, fname):
self.lines = CharmmFile(fname, 'r').readlines()
self.line_number = 0
def __iter__(self):
return iter(self.lines)
def rewind(self):
""" Return to the beginning of the file """
self.line_number = 0
def next_section(self):
"""
Fast-forwards the file to the next CHARMM command section
Returns: (str, list)
- The first string is the line defining the section that's being
returned
- The list is a list of all lines contained in the section
excluding the "read <blah>" and "end" lines.
Notes:
The line pointer will be set to the line defining the
"""
lines = []
while self.line_number < len(self.lines):
line = self.lines[self.line_number].strip()
if line[:4].lower() == 'read':
title = line.strip()
self.line_number += 1
line = self.lines[self.line_number]
while line and not line.strip().lower().startswith('end'):
lines.append(line)
self.line_number += 1
line = self.lines[self.line_number]
return title, lines
self.line_number += 1
# No sections left
return None, None
def __del__(self):
pass
"""
This package contains exceptions that may be raised by the CHARMM components of
the OpenMM Application layer
Author: Jason M. Swails
Contributors:
Date: April 9, 2014
"""
class CharmmPSFError(CharmmError):
""" If there is a problem parsing CHARMM PSF files """
class SplitResidueWarning(CharmmWarning):
""" For if a residue with the same number but different names is split """
class ResidueError(CharmmError):
""" For when there are problems defining a residue """
class CharmmPSFWarning(CharmmWarning):
""" For non-fatal PSF parsing issues """
class CharmmFileError(CharmmError):
""" If there is a problem parsing CHARMM files """
class MissingParameter(CharmmError):
""" If a parameter is missing from a database """
class CmapError(CharmmError):
""" For an error arising from CMAP grid incompatibilities """
class BondError(CharmmError):
""" Prevent an atom from bonding to itself """
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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