Source code for gromacs.fileformats.mdp

# GromacsWrapper: formats.py
# Copyright (c) 2009-2011 Oliver Beckstein <orbeckst@gmail.com>
# Released under the GNU Public License 3 (or higher, your choice)
# See the file COPYING for details.
"""
Gromacs parameter MDP file format
=================================

The `.mdp file`_ contains a list of keywords that are used to set up a
simulation with :class:`~gromacs.tools.Grompp`. The class :class:`MDP`
parses this file and provides access to the keys and values as ordered
dictionary.

.. _`.mdp file`: http://www.gromacs.org/Documentation/File_Formats/.mdp_File

.. autoclass:: MDP
   :members:
"""


import os, errno
import re
import warnings
import numpy


from ..exceptions import ParseError, AutoCorrectionWarning
from .. import utilities
from collections import OrderedDict as odict

import logging


[docs] class MDP(odict, utilities.FileUtils): """Class that represents a Gromacs mdp run input file. The MDP instance is an ordered dictionary. - *Parameter names* are keys in the dictionary. - *Comments* are sequentially numbered with keys Comment0001, Comment0002, ... - *Empty lines* are similarly preserved as Blank0001, .... When writing, the dictionary is dumped in the recorded order to a file. Inserting keys at a specific position is not possible. Currently, comments after a parameter on the same line are discarded. Leading and trailing spaces are always stripped. .. SeeAlso:: For editing a mdp file one can also use :func:`gromacs.cbook.edit_mdp` (which works like a poor replacement for sed). """ default_extension = "mdp" logger = logging.getLogger("gromacs.formats.MDP") COMMENT = re.compile(r"""\s*;\s*(?P<value>.*)""") # eat initial ws # see regex in cbook.edit_mdp() PARAMETER = re.compile( r""" \s*(?P<parameter>[^=]+?)\s*=\s* # parameter (ws-stripped), before '=' (?P<value>[^;]*) # value (stop before comment=;) (?P<comment>\s*;.*)? # optional comment """, re.VERBOSE, ) def __init__(self, filename=None, autoconvert=True, **kwargs): """Initialize mdp structure. :Arguments: *filename* read from mdp file *autoconvert* : boolean ``True`` converts numerical values to python numerical types; ``False`` keeps everything as strings [``True``] *kwargs* Populate the MDP with key=value pairs. (NO SANITY CHECKS; and also does not work for keys that are not legal python variable names such as anything that includes a minus '-' sign or starts with a number). """ super(MDP, self).__init__( **kwargs ) # can use kwargs to set dict! (but no sanity checks!) self.autoconvert = autoconvert if filename is not None: self._init_filename(filename) self.read(filename) def _transform(self, value): if self.autoconvert: return utilities.autoconvert(value) else: return value.rstrip()
[docs] def read(self, filename=None): """Read and parse mdp file *filename*.""" self._init_filename(filename) def BLANK(i): return "B{0:04d}".format(i) def COMMENT(i): return "C{0:04d}".format(i) data = odict() iblank = icomment = 0 with open(self.real_filename) as mdp: for line in mdp: line = line.strip() if len(line) == 0: iblank += 1 data[BLANK(iblank)] = "" continue m = self.COMMENT.match(line) if m: icomment += 1 data[COMMENT(icomment)] = m.group("value") continue # parameter m = self.PARAMETER.match(line) if m: # check for comments after parameter?? -- currently discarded parameter = m.group("parameter") value = self._transform(m.group("value")) data[parameter] = value else: errmsg = "{filename!r}: unknown line in mdp file, {line!r}".format( **vars() ) self.logger.error(errmsg) raise ParseError(errmsg) super(MDP, self).update(data)
[docs] def write(self, filename=None, skipempty=False): """Write mdp file to *filename*. :Keywords: *filename* output mdp file; default is the filename the mdp was read from *skipempty* : boolean ``True`` removes any parameter lines from output that contain empty values [``False``] .. Note:: Overwrites the file that the mdp was read from if no *filename* supplied. """ with open(self.filename(filename, ext="mdp"), "w") as mdp: for k, v in self.items(): if k[0] == "B": # blank line mdp.write("\n") elif k[0] == "C": # comment mdp.write("; {v!s}\n".format(**vars())) else: # parameter = value if skipempty and (v == "" or v is None): continue if isinstance(v, str) or not hasattr(v, "__iter__"): mdp.write("{k!s} = {v!s}\n".format(**vars())) else: mdp.write("{} = {}\n".format(k, " ".join(map(str, v))))