def edit_mdp(mdp, new_mdp=None, extend_parameters=None, **substitutions):
if new_mdp is None:<EOL><INDENT>new_mdp = mdp<EOL><DEDENT>if extend_parameters is None:<EOL><INDENT>extend_parameters = ['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>extend_parameters = list(asiterable(extend_parameters))<EOL><DEDENT>substitutions = {k: v for k,v in substitutions.items() if v is not None}<EOL>params = list(substitutions.keys())   <EOL>def demangled(p):<EOL><INDENT>"""<STR_LIT>"""<EOL>return p.replace('<STR_LIT:_>', '<STR_LIT>')  <EOL><DEDENT>patterns = {parameter:<EOL>re.compile("""<STR_LIT>""".format(demangled(parameter)), re.VERBOSE)<EOL>for parameter in substitutions}<EOL>with tempfile.TemporaryFile() as target:<EOL><INDENT>with open(mdp, '<STR_LIT:rb>') as src:<EOL><INDENT>logger.info("<STR_LIT>".format(mdp, substitutions.keys()))<EOL>for line in src:<EOL><INDENT>line = line.decode('<STR_LIT:utf-8>')<EOL>new_line = line.strip()  <EOL>for p in params[:]:<EOL><INDENT>m = patterns[p].match(new_line)<EOL>if m:<EOL><INDENT>if m.group('<STR_LIT>') is None:<EOL><INDENT>comment = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>comment = "<STR_LIT:U+0020>"+m.group('<STR_LIT>')<EOL><DEDENT>assignment = m.group('<STR_LIT>')<EOL>if not assignment.endswith('<STR_LIT:U+0020>'):<EOL><INDENT>assignment += '<STR_LIT:U+0020>'<EOL><DEDENT>new_line = assignment<EOL>if p in extend_parameters:<EOL><INDENT>new_line += str(m.group('<STR_LIT:value>')) + '<STR_LIT:U+0020>'<EOL><DEDENT>value = "<STR_LIT:U+0020>".join(map(str, asiterable(substitutions[p])))<EOL>new_line += value + comment<EOL>params.remove(p)<EOL>break<EOL><DEDENT><DEDENT>target.write((new_line+'<STR_LIT:\n>').encode('<STR_LIT:utf-8>'))<EOL><DEDENT><DEDENT>target.seek(<NUM_LIT:0>)<EOL>with open(new_mdp, '<STR_LIT:wb>') as final:<EOL><INDENT>shutil.copyfileobj(target, final)<EOL><DEDENT><DEDENT>if len(params) > <NUM_LIT:0>:<EOL><INDENT>logger.warn("<STR_LIT>".format(**vars()))<EOL><DEDENT>return {p: substitutions[p] for p in params}<EOL>
Change values in a Gromacs mdp file.

    Parameters and values are supplied as substitutions, eg ``nsteps=1000``.

    By default the template mdp file is **overwritten in place**.

    If a parameter does not exist in the template then it cannot be substituted
    and the parameter/value pair is returned. The user has to check the
    returned list in order to make sure that everything worked as expected. At
    the moment it is not possible to automatically append the new values to the
    mdp file because of ambiguities when having to replace dashes in parameter
    names with underscores (see the notes below on dashes/underscores).

    If a parameter is set to the value ``None`` then it will be ignored.

    :Arguments:
        *mdp* : filename
            filename of input (and output filename of ``new_mdp=None``)
        *new_mdp* : filename
            filename of alternative output mdp file [None]
        *extend_parameters* : string or list of strings
            single parameter or list of parameters for which the new values
            should be appended to the existing value in the mdp file. This
            makes mostly sense for a single parameter, namely 'include', which
            is set as the default. Set to ``[]`` to disable. ['include']
        *substitutions*
            parameter=value pairs, where parameter is defined by the Gromacs
            mdp file; dashes in parameter names have to be replaced by
            underscores. If a value is a list-like object then the items are
            written as a sequence, joined with spaces, e.g. ::

               ref_t=[310,310,310] --->  ref_t = 310 310 310

    :Returns:
        Dict of parameters that have *not* been substituted.

    **Example** ::

       edit_mdp('md.mdp', new_mdp='long_md.mdp', nsteps=100000, nstxtcout=1000, lincs_iter=2)

    .. Note::

       * Dashes in Gromacs mdp parameters have to be replaced by an underscore
         when supplied as python keyword arguments (a limitation of python). For example
         the MDP syntax is  ``lincs-iter = 4`` but the corresponding  keyword would be
         ``lincs_iter = 4``.
       * If the keyword is set as a dict key, eg ``mdp_params['lincs-iter']=4`` then one
         does not have to substitute.
       * Parameters *aa_bb* and *aa-bb* are considered the same (although this should
         not be a problem in practice because there are no mdp parameters that only
         differ by a underscore).
       * This code is more compact in ``Perl`` as one can use ``s///`` operators:
         ``s/^(\s*${key}\s*=\s*).*/$1${val}/``

    .. SeeAlso:: One can also load the mdp file with
                :class:`gromacs.formats.MDP`, edit the object (a dict), and save it again.