Instruction:
Can you create a Python 3 function that
creates a top level logger with the given name and logfile.

Response:
def create(logger_name, logfile='gromacs.log'):
    """Create a top level logger.

    - The file logger logs everything (including DEBUG).
    - The console logger only logs INFO and above.

    Logging to a file and the console.

    See http://docs.python.org/library/logging.html?#logging-to-multiple-destinations

    The top level logger of the library is named 'gromacs'.  Note that
    we are configuring this logger with console output. If the root
    logger also does this then we will get two output lines to the
    console. We'll live with this because this is a simple
    convenience library...
    """

    logger = logging.getLogger(logger_name)

    logger.setLevel(logging.DEBUG)

    logfile = logging.FileHandler(logfile)
    logfile_formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
    logfile.setFormatter(logfile_formatter)
    logger.addHandler(logfile)

    # define a Handler which writes INFO messages or higher to the sys.stderr
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    # set a format which is simpler for console use
    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
    console.setFormatter(formatter)

    logger.addHandler(console)

    return logger


Instruction:
Implement a Python 3 function for
generating a dictionary of template filenames and their contents.

Response:
def _generate_template_dict(dirname):
    """Generate a list of included files *and* extract them to a temp space.

    Templates have to be extracted from the egg because they are used
    by external code. All template filenames are stored in
    :data:`config.templates`.
    """
    return dict((resource_basename(fn), resource_filename(__name__, dirname +'/'+fn))
                for fn in resource_listdir(__name__, dirname)
                if not fn.endswith('~'))


Instruction:
Can you tell what is the following Python 3 function doing
def resource_basename(resource):
    if resource.endswith('/'):
         resource = resource[:-1]
    parts = resource.split('/')
    return parts[-1]

Response: Returns the last component of a resource.


Instruction:
Write a Python 3 function for
finding template file t and return its real path.

Response:
def get_template(t):
    """Find template file *t* and return its real path.

    *t* can be a single string or a list of strings. A string
    should be one of

    1. a relative or absolute path,
    2. a file in one of the directories listed in :data:`gromacs.config.path`,
    3. a filename in the package template directory (defined in the template dictionary
       :data:`gromacs.config.templates`) or
    4. a key into :data:`~gromacs.config.templates`.

    The first match (in this order) is returned. If the argument is a
    single string then a single string is returned, otherwise a list
    of strings.

    :Arguments: *t* : template file or key (string or list of strings)
    :Returns:   os.path.realpath(*t*) (or a list thereof)
    :Raises:    :exc:`ValueError` if no file can be located.

    """
    templates = [_get_template(s) for s in utilities.asiterable(t)]
    if len(templates) == 1:
         return templates[0]
    return templates


Instruction:
Can you write a function in Python 3 where it
returns a single template file.

Response:
def _get_template(t):
    """Return a single template *t*."""
    if os.path.exists(t):           # 1) Is it an accessible file?
         pass
    else:
         _t = t
         _t_found = False
         for d in path:              # 2) search config.path
              p = os.path.join(d, _t)
              if os.path.exists(p):
                   t = p
                   _t_found = True
                   break
         _t = os.path.basename(t)
         if not _t_found:            # 3) try template dirs
              for p in templates.values():
                   if _t == os.path.basename(p):
                        t = p
                        _t_found = True     # NOTE: in principle this could match multiple
                        break               #       times if more than one template dir existed.
         if not _t_found:            # 4) try it as a key into templates
              try:
                   t = templates[t]
              except KeyError:
                   pass
              else:
                   _t_found = True
         if not _t_found:            # 5) nothing else to try...
              raise ValueError("Failed to locate the template file {t!r}.".format(**vars()))
    return os.path.realpath(t)


Instruction:
How would you explain what the following Python 3 function does
def get_configuration(filename=CONFIGNAME):
    global cfg, configuration    # very iffy --- most of the whole config mod should a class

    #: :data:`cfg` is the instance of :class:`GMXConfigParser` that makes all
    #: global configuration data accessible
    cfg = GMXConfigParser(filename=filename)   # update module-level cfg
    globals().update(cfg.configuration)        # update configdir, templatesdir ...
    configuration = cfg.configuration          # update module-level configuration
    return cfg

Response: Reads and parses the configuration file.


Instruction:
Write a Python 3 script for
preparing a default GromacsWrapper global environment.

Response:
def setup(filename=CONFIGNAME):
     """Prepare a default GromacsWrapper global environment.

     1) Create the global config file.
     2) Create the directories in which the user can store template and config files.

     This function can be run repeatedly without harm.
     """
     # setup() must be separate and NOT run automatically when config
     # is loaded so that easy_install installations work
     # (otherwise we get a sandbox violation)
     # populate cfg with defaults (or existing data)
     get_configuration()
     if not os.path.exists(filename):
          with open(filename, 'w') as configfile:
               cfg.write(configfile)  # write the default file so that user can edit
               msg = "NOTE: GromacsWrapper created the configuration file \n\t%r\n" \
                     "      for you. Edit the file to customize the package." % filename
               print(msg)

     # directories
     for d in config_directories:
          utilities.mkdir_p(d)


Instruction:
Explain what the following Python 3 code does
def check_setup():

     if "GROMACSWRAPPER_SUPPRESS_SETUP_CHECK" in os.environ:
         return True

     missing = [d for d in config_directories if not os.path.exists(d)]
     if len(missing) > 0:
         print("NOTE: Some configuration directories are not set up yet: ")
         print("\t{0!s}".format('\n\t'.join(missing)))
         print("NOTE: You can create the configuration file and directories with:")
         print("\t>>> import gromacs")
         print("\t>>> gromacs.config.setup()")
         return False
     return True

Response: Check if templates directories are setup and issue a warning and help.


Instruction:
Can you create a Python 3 function that
sets the environment variables loaded by GMXRC into the current Python environment.

Response:
def set_gmxrc_environment(gmxrc):
    """Set the environment from ``GMXRC`` provided in *gmxrc*.

    Runs ``GMXRC`` in a subprocess and puts environment variables loaded by it
    into this Python environment.

    If *gmxrc* evaluates to ``False`` then nothing is done. If errors occur
    then only a warning will be logged. Thus, it should be safe to just call
    this function.
    """
    # only v5: 'GMXPREFIX', 'GROMACS_DIR'
    envvars = ['GMXBIN', 'GMXLDLIB', 'GMXMAN', 'GMXDATA',
               'LD_LIBRARY_PATH', 'MANPATH', 'PKG_CONFIG_PATH',
               'PATH',
               'GMXPREFIX', 'GROMACS_DIR']
    # in order to keep empty values, add ___ sentinels around result
    # (will be removed later)
    cmdargs = ['bash', '-c', ". {0} && echo {1}".format(gmxrc,
               ' '.join(['___${{{0}}}___'.format(v) for v in envvars]))]

    if not gmxrc:
        logger.debug("set_gmxrc_environment(): no GMXRC, nothing done.")
        return

    try:
        out = subprocess.check_output(cmdargs)
        out = out.strip().split()
        for key, value in zip(envvars, out):
            value = str(value.decode('ascii').replace('___', ''))  # remove sentinels
            os.environ[key] = value
            logger.debug("set_gmxrc_environment(): %s = %r", key, value)
    except (subprocess.CalledProcessError, OSError):
        logger.warning("Failed to automatically set the Gromacs environment"
                       "from GMXRC=%r", gmxrc)


Instruction:
How would you implement a function in Python 3 that
gets all tool names from all configured groups.

Response:
def get_tool_names():
    """ Get tool names from all configured groups.

    :return: list of tool names
    """
    names = []
    for group in cfg.get('Gromacs', 'groups').split():
        names.extend(cfg.get('Gromacs', group).split())
    return names


Instruction:
Write a Python 3 script to
return a dictionary of variables that we can use as globals in the module.

Response:
def configuration(self):
          """Dict of variables that we make available as globals in the module.

          Can be used as ::

             globals().update(GMXConfigParser.configuration)        # update configdir, templatesdir ...
          """
          configuration = {
               'configfilename': self.filename,
               'logfilename': self.getpath('Logging', 'logfilename'),
               'loglevel_console': self.getLogLevel('Logging', 'loglevel_console'),
               'loglevel_file': self.getLogLevel('Logging', 'loglevel_file'),
               'configdir': self.getpath('DEFAULT', 'configdir'),
               'qscriptdir': self.getpath('DEFAULT', 'qscriptdir'),
               'templatesdir': self.getpath('DEFAULT', 'templatesdir'),
               }
          configuration['path'] = [os.path.curdir,
                                   configuration['qscriptdir'],
                                   configuration['templatesdir']]
          return configuration


Instruction:
Can you create a Python 3 function that
returns option as an expanded path.

Response:
def getpath(self, section, option):
          """Return option as an expanded path."""
          return os.path.expanduser(os.path.expandvars(self.get(section, option)))


Instruction:
Can you write a function in Python 3 where it
returns the textual representation of the logging level option or the number.

Response:
def getLogLevel(self, section, option):
          """Return the textual representation of logging level 'option' or the number.

          Note that option is always interpreted as an UPPERCASE string
          and hence integer log levels will not be recognized.

          .. SeeAlso: :mod:`logging` and :func:`logging.getLevelName`
          """
          return logging.getLevelName(self.get(section, option).upper())


Instruction:
Make a summary of the following Python 3 code
def save(self, filename):
        cPickle.dump(self, open(self._canonicalize(filename), 'wb'),
                     protocol=cPickle.HIGHEST_PROTOCOL)

Response: Save the whole collection to filename.


Instruction:
How would you explain what the following Python 3 function does
def load(self, filename, append=False):
        tmp = cPickle.load(open(self._canonicalize(filename), 'rb'))
        if append:
            self.extend(tmp)
        else:
            self[:] = tmp[:]
        del tmp

Response: Load a collection from a pickled file.


Instruction:
Explain what the following Python 3 code does
def _canonicalize(self, filename):
        path, ext = os.path.splitext(filename)
        if not ext:
            ext = ".collection"
        return path + ext

Response: Use .collection as extension unless provided


Instruction:
Can you tell what is the following Python 3 function doing
def register(self,flag):
        super(Flags,self).__setitem__(flag.name,flag)

Response: Register a new flag instance with the Flags registry.


Instruction:
Make a summary of the following Python 3 code
def update(self,*flags):
        super(Flags,self).update([(flag.name,flag) for flag in flags])

Response: Update the flags registry with a list of : class : Flag instances.


Instruction:
How would you implement a function in Python 3 that
scales dihedrals in a molecule.

Response:
def scale_dihedrals(mol, dihedrals, scale, banned_lines=None):
        """Scale dihedral angles"""

        if banned_lines is None:
                banned_lines = []
        new_dihedrals = []
        for dh in mol.dihedrals:
                atypes = dh.atom1.get_atomtype(), dh.atom2.get_atomtype(), dh.atom3.get_atomtype(), dh.atom4.get_atomtype()
                atypes = [a.replace("_", "").replace("=","") for a in atypes]

                # special-case: this is a [ dihedral ] override in molecule block, continue and don't match
                if dh.gromacs['param'] != []:
                    for p in dh.gromacs['param']:
                        p['kch'] *= scale
                    new_dihedrals.append(dh)
                    continue

                for iswitch in range(32):
                        if  (iswitch%2==0 ):
                                a1=atypes[0]; a2=atypes[1]; a3=atypes[2]; a4=atypes[3]
                        else:
                                a1=atypes[3]; a2=atypes[2]; a3=atypes[1]; a4=atypes[0]

                        if((iswitch//2)%2==1): a1="X";
                        if((iswitch//4)%2==1): a2="X";
                        if((iswitch//8)%2==1): a3="X";
                        if((iswitch//16)%2==1): a4="X";
                        key = "{0}-{1}-{2}-{3}-{4}".format(a1, a2, a3, a4, dh.gromacs['func'])
                        if (key in dihedrals):
                                for i, dt in enumerate(dihedrals[key]):
                                        dhA = copy.deepcopy(dh)
                                        param = copy.deepcopy(dt.gromacs['param'])
                                        # Only check the first dihedral in a list
                                        if not dihedrals[key][0].line in banned_lines:
                                                for p in param: p['kchi'] *= scale
                                        dhA.gromacs['param'] = param
                                        #if key == "CT3-C-NH1-CT1-9": print i, dt, key
                                        if i == 0:
                                                dhA.comment = "; banned lines {0} found={1}\n".format(" ".join(
                                                        map(str, banned_lines)), 1 if dt.line in banned_lines else 0)
                                                dhA.comment += "; parameters for types {}-{}-{}-{}-9 at LINE({})\n".format(
                                                        dhA.atom1.atomtype, dhA.atom2.atomtype, dhA.atom3.atomtype,
                                                        dhA.atom4.atomtype, dt.line).replace("_","")
                                        name = "{}-{}-{}-{}-9".format(dhA.atom1.atomtype, dhA.atom2.atomtype,
                                                                      dhA.atom3.atomtype, dhA.atom4.atomtype).replace("_","")
                                        #if name == "CL-CTL2-CTL2-HAL2-9": print dihedrals[key], key
                                        new_dihedrals.append(dhA)
                                break

        mol.dihedrals = new_dihedrals
        #assert(len(mol.dihedrals) == new_dihedrals)
        return mol


Instruction:
Can you generate a brief explanation for the following Python 3 code
def partial_tempering(topfile="processed.top", outfile="scaled.top", banned_lines='',
                      scale_lipids=1.0, scale_protein=1.0):
        """Set up topology for partial tempering (REST2) replica exchange.

        .. versionchanged:: 0.7.0
           Use keyword arguments instead of an `args` Namespace object.
        """

        banned_lines = map(int, banned_lines.split())
        top = TOP(topfile)
        groups = [("_", float(scale_protein)), ("=", float(scale_lipids))]

        #
        # CMAPTYPES
        #
        cmaptypes = []
        for ct in top.cmaptypes:
                cmaptypes.append(ct)
                for gr, scale in groups:
                        ctA = copy.deepcopy(ct)
                        ctA.atype1 += gr
                        ctA.atype2 += gr
                        ctA.atype3 += gr
                        ctA.atype4 += gr
                        ctA.atype8 += gr
                        ctA.gromacs['param'] = [ v*scale for v in ct.gromacs['param'] ]
                        cmaptypes.append(ctA)
        logger.debug("cmaptypes was {0}, is {1}".format(len(top.cmaptypes), len(cmaptypes)))
        top.cmaptypes = cmaptypes

        #
        # ATOMTYPES
        #
        atomtypes = []
        for at in top.atomtypes:
                atomtypes.append(at)
                for gr, scale in groups:
                        atA = copy.deepcopy(at)
                        atA.atnum = atA.atype
                        atA.atype += gr
                        atA.gromacs['param']['lje'] *= scale
                        atomtypes.append(atA)
        top.atomtypes = atomtypes

        #
        # PAIRTYPES
        #
        pairtypes = []
        for pt in top.pairtypes:
                pairtypes.append(pt)
                for gr, scale in groups:
                        ptA = copy.deepcopy(pt)
                        ptA.atype1 += gr
                        ptA.atype2 += gr
                        ptA.gromacs['param']['lje14'] *= scale

                        pairtypes.append(ptA)
        top.pairtypes = pairtypes

        #
        # BONDTYPES
        #
        bondtypes = []
        for bt in top.bondtypes:
                bondtypes.append(bt)
                for gr, scale in groups:
                        btA = copy.deepcopy(bt)
                        btA.atype1 += gr
                        btA.atype2 += gr
                        bondtypes.append(btA)
        top.bondtypes = bondtypes

        #
        # ANGLETYPES
        #
        angletypes = []
        for at in top.angletypes:
                angletypes.append(at)
                for gr, scale in groups:
                        atA = copy.deepcopy(at)
                        atA.atype1 += gr
                        atA.atype2 += gr
                        atA.atype3 += gr
                        angletypes.append(atA)
        top.angletypes = angletypes

        #
        # Build dihedral dictionary
        #
        dihedraltypes = {}
        for dt in top.dihedraltypes:
                dt.disabled = True
                dt.comment = "; type={0!s}-{1!s}-{2!s}-{3!s}-9\n; LINE({4:d}) ".format(
                        dt.atype1, dt.atype2, dt.atype3, dt.atype4, dt.line)
                dt.comment = dt.comment.replace("_","")

                #if "X-CTL2-CTL2-X-9" in dt.comment: print dt
                name = "{0}-{1}-{2}-{3}-{4}".format(dt.atype1, dt.atype2, dt.atype3, dt.atype4, dt.gromacs['func'])
                if not name in dihedraltypes:
                        dihedraltypes[name] = []
                dihedraltypes[name].append(dt)
        logger.debug("Build dihedraltypes dictionary with {0} entries".format(len(dihedraltypes)))

        #
        # Build improper dictionary
        #
        impropertypes = {}
        for it in top.impropertypes:
                it.disabled = True
                it.comment = "; LINE({0:d}) ".format(it.line)
                name = "{0}-{1}-{2}-{3}-{4}".format(
                        it.atype1, it.atype2, it.atype3, it.atype4, it.gromacs['func'])
                if not name in impropertypes:
                        impropertypes[name] = []
                impropertypes[name].append(it)
        logger.debug("Build impropertypes dictionary with {0} entries".format(len(impropertypes)))

        for molname_mol in top.dict_molname_mol:
            if not 'Protein' in molname_mol:
                continue
            mol = top.dict_molname_mol[molname_mol]
            for at in mol.atoms:
                at.charge *= math.sqrt(scale_protein)
            mol = scale_dihedrals(mol, dihedraltypes, scale_protein, banned_lines)
            mol = scale_impropers(mol, impropertypes, 1.0, banned_lines)

        top.write(outfile)

Response: Set up topology for partial tempering.


Instruction:
Implement a function in Python 3 to
convert obj to unicode if it can be converted.

Response:
def to_unicode(obj):
    """Convert obj to unicode (if it can be be converted).

    Conversion is only attempted if `obj` is a string type (as
    determined by :data:`six.string_types`).

    .. versionchanged:: 0.7.0
       removed `encoding keyword argument

    """
    if not isinstance(obj, six.string_types):
        return obj

    try:
        obj = six.text_type(obj)
    except TypeError:
        pass
    return obj


Instruction:
Write a Python 3 function that can
convert string x to the most useful type i. e. int float or unicode string.

Response:
def besttype(x):
    """Convert string x to the most useful type, i.e. int, float or unicode string.

    If x is a quoted string (single or double quotes) then the quotes
    are stripped and the enclosed string returned.

    .. Note::

       Strings will be returned as Unicode strings (using :func:`to_unicode`).

    .. versionchanged:: 0.7.0
       removed `encoding keyword argument
    """
    x = to_unicode(x)  # make unicode as soon as possible
    try:
        x = x.strip()
    except AttributeError:
        pass
    m = re.match(r"""['"](?P<value>.*)["']$""", x)
    if m is None:
        # not a quoted string, try different types
        for converter in int, float, to_unicode:   # try them in increasing order of lenience
            try:
                return converter(x)
            except ValueError:
                pass
    else:
        # quoted string
        x = to_unicode(m.group('value'))
    return x


Instruction:
Can you tell what is the following Python 3 function doing
def to_int64(a):
    # build new dtype and replace i4 --> i8
    def promote_i4(typestr):
        if typestr[1:] == 'i4':
            typestr = typestr[0]+'i8'
        return typestr

    dtype = [(name, promote_i4(typestr)) for name,typestr in a.dtype.descr]
    return a.astype(dtype)

Response: Return view of the recarray with all int32 cast to int64.


Instruction:
Write a Python 3 script for
slowing conversion of a recarray into a list of records with python types.

Response:
def irecarray_to_py(a):
    """Slow conversion of a recarray into a list of records with python types.

    Get the field names from :attr:`a.dtype.names`.

    :Returns: iterator so that one can handle big input arrays
    """
    pytypes = [pyify(typestr) for name,typestr in a.dtype.descr]
    def convert_record(r):
        return tuple([converter(value) for converter, value in zip(pytypes,r)])
    return (convert_record(r) for r in a)


Instruction:
Explain what the following Python 3 code does
def _convert_fancy(self, field):
        if self.sep is False:
            x = self._convert_singlet(field)
        else:
            x = tuple([self._convert_singlet(s) for s in field.split(self.sep)])
            if len(x) == 0:
                x = ''
            elif len(x) == 1:
                x = x[0]
        #print "%r --> %r" % (field, x)
        return x

Response: Convert to a list and convert list elements.


Instruction:
Write a Python 3 function for
parsing the xpm file and populate the XPM. array attribute.

Response:
def parse(self):
        """Parse the xpm file and populate :attr:`XPM.array`."""
        with utilities.openany(self.real_filename) as xpm:
            # Read in lines until we find the start of the array
            meta = [xpm.readline()]
            while not meta[-1].startswith("static char *gromacs_xpm[]"):
                meta.append(xpm.readline())

            # The next line will contain the dimensions of the array
            dim = xpm.readline()
            # There are four integers surrounded by quotes
            # nx: points along x, ny: points along y, nc: ?, nb: stride x
            nx, ny, nc, nb = [int(i) for i in self.unquote(dim).split()]

            # The next dim[2] lines contain the color definitions
            # Each pixel is encoded by dim[3] bytes, and a comment
            # at the end of the line contains the corresponding value
            colors = dict([self.col(xpm.readline()) for i in range(nc)])

            if self.autoconvert:
                autoconverter = Autoconverter(mode="singlet")
                for symbol, value in colors.items():
                    colors[symbol] = autoconverter.convert(value)
                self.logger.debug("Autoconverted colours: %r", colors)

            # make an array containing all possible values and let numpy figure out the dtype
            dtype = numpy.array(colors.values()).dtype
            self.logger.debug("Guessed array type: %s", dtype.name)

            # pre-allocate array
            data = numpy.zeros((int(nx/nb), ny), dtype=dtype)

            self.logger.debug("dimensions: NX=%d NY=%d strideX=%d (NC=%d) --> (%d, %d)",
                              nx, ny, nb, nc, nx/nb, ny)

            iy = 0
            xval = []
            yval = []
            autoconverter = Autoconverter(mode="singlet")
            for line in xpm:
                if line.startswith("/*"):
                    # lines '/* x-axis:' ... and '/* y-axis:' contain the
                    # values of x and y coordinates
                    s = self.uncomment(line).strip()
                    if s.startswith('x-axis:'):
                        xval.extend([autoconverter.convert(x) for x in s[7:].split()])
                    elif s.startswith('y-axis:'):
                        yval.extend([autoconverter.convert(y) for y in s[7:].split()])
                    continue
                s = self.unquote(line)
                # Joao M. Damas <jmdamas@itqb.unl.pt> suggests on gmx-users (24 Oct 2014)
                # that the next line should read:
                #
                #  data[:, iy]  =  [colors[j[k:k+nb]] for k in range(0,nx*nb,nb)]
                #
                # "if one is using higher -nlevels for the .xpm construction (in g_rms, for example)"
                # However, without a test case I am not eager to change it right away so in
                # case some faulty behavior is discovered with the XPM reader then this comment
                # might be helpful. --- Oliver 2014-10-25
                data[:, iy] = [colors[s[k:k+nb]] for k in range(0,nx,nb)]
                self.logger.debug("read row %d with %d columns: '%s....%s'",
                                  iy, data.shape[0], s[:4], s[-4:])
                iy += 1  # for next row

        self.xvalues = numpy.array(xval)
        if self.reverse:
            self.logger.debug("reversed row order, reverse=%r", self.reverse)
            self.__array = data[:, ::-1]
            self.yvalues = numpy.array(yval)
        else:
            self.__array = data
            self.yvalues = numpy.array(yval)[::-1]


Instruction:
How would you implement a function in Python 3 that
parses a colour specification and return color and value.

Response:
def col(self, c):
        """Parse colour specification"""
        m = self.COLOUR.search(c)
        if not m:
            self.logger.fatal("Cannot parse colour specification %r.", c)
            raise ParseError("XPM reader: Cannot parse colour specification {0!r}.".format(c))
        value = m.group('value')
        color = m.group('symbol')
        self.logger.debug("%s: %s %s\n", c.strip(), color, value)
        return color, value


Instruction:
Write a Python 3 function that can
run the command ; args and kwargs are added or replaced the ones given to the constructor.

Response:
def run(self, *args, **kwargs):
        """Run the command; args/kwargs are added or replace the ones given to the constructor."""
        _args, _kwargs = self._combine_arglist(args, kwargs)
        results, p = self._run_command(*_args, **_kwargs)
        return results


Instruction:
Make a summary of the following Python 3 code
def _combine_arglist(self, args, kwargs):
        _args = self.args + args
        _kwargs = self.kwargs.copy()
        _kwargs.update(kwargs)
        return _args, _kwargs

Response: Combine the default values and the supplied values.


Instruction:
Can you implement a function in Python 3 that
executes the command and return the output and stderr.

Response:
def _run_command(self, *args, **kwargs):
        """Execute the command; see the docs for __call__.

        :Returns: a tuple of the *results* tuple ``(rc, stdout, stderr)`` and
                  the :class:`Popen` instance.
        """
        # hack to run command WITHOUT input (-h...) even though user defined
        # input (should have named it "ignore_input" with opposite values...)
        use_input = kwargs.pop('use_input', True)

        # logic for capturing output (see docs on I/O and the flags)
        capturefile = None
        if environment.flags['capture_output'] is True:
            # capture into Python vars (see subprocess.Popen.communicate())
            kwargs.setdefault('stderr', PIPE)
            kwargs.setdefault('stdout', PIPE)
        elif environment.flags['capture_output'] == "file":
            if 'stdout' in kwargs and 'stderr' in kwargs:
                pass
            else:
                # XXX: not race or thread proof; potentially many commands write to the same file
                fn = environment.flags['capture_output_filename']
                capturefile = file(fn, "w")   # overwrite (clobber) capture file
                if 'stdout' in kwargs and 'stderr' not in kwargs:
                    # special case of stdout used by code but stderr should be captured to file
                    kwargs.setdefault('stderr', capturefile)
                else:
                    # merge stderr with stdout and write stdout to file
                    # (stderr comes *before* stdout in capture file, could split...)
                    kwargs.setdefault('stderr', STDOUT)
                    kwargs.setdefault('stdout', capturefile)

        try:
            p = self.Popen(*args, **kwargs)
            out, err = p.communicate(use_input=use_input) # special Popen knows input!
        except:
            if capturefile is not None:
                logger.error("Use captured command output in %r for diagnosis.", capturefile)
            raise
        finally:
            if capturefile is not None:
                capturefile.close()
        rc = p.returncode
        return (rc, out, err), p


Instruction:
Here you have a function in Python 3, explain what it does
def _commandline(self, *args, **kwargs):
         # transform_args() is a hook (used in GromacsCommand very differently!)
        return [self.command_name] + self.transform_args(*args, **kwargs)

Response: Returns the command line as a list.


Instruction:
How would you explain what the following Python 3 function does
def commandline(self, *args, **kwargs):
        # this mirrors the setup in run()
        _args, _kwargs = self._combine_arglist(args, kwargs)
        return self._commandline(*_args, **_kwargs)

Response: Returns the commandline that run() uses.


Instruction:
Make a summary of the following Python 3 code
def Popen(self, *args, **kwargs):
        stderr = kwargs.pop('stderr', None)     # default: print to stderr (if STDOUT then merge)
        if stderr is False:                     # False: capture it
            stderr = PIPE
        elif stderr is True:
            stderr = None                       # use stderr

        stdout = kwargs.pop('stdout', None)     # either set to PIPE for capturing output
        if stdout is False:                     # ... or to False
            stdout = PIPE
        elif stdout is True:
            stdout = None                       # for consistency, make True write to screen

        stdin = kwargs.pop('stdin', None)
        input = kwargs.pop('input', None)

        use_shell = kwargs.pop('use_shell', False)
        if input:
            stdin = PIPE
            if isinstance(input, six.string_types) and not input.endswith('\n'):
                # make sure that input is a simple string with \n line endings
                input = six.text_type(input) + '\n'
            else:
                try:
                    # make sure that input is a simple string with \n line endings
                    input = '\n'.join(map(six.text_type, input)) + '\n'
                except TypeError:
                    # so maybe we are a file or something ... and hope for the best
                    pass

        cmd = self._commandline(*args, **kwargs)   # lots of magic happening here
                                                   # (cannot move out of method because filtering of stdin etc)
        try:
            p = PopenWithInput(cmd, stdin=stdin, stderr=stderr, stdout=stdout,
                               universal_newlines=True, input=input, shell=use_shell)
        except OSError as err:
            logger.error(" ".join(cmd))            # log command line
            if err.errno == errno.ENOENT:
                errmsg = "Failed to find Gromacs command {0!r}, maybe its not on PATH or GMXRC must be sourced?".format(self.command_name)
                logger.fatal(errmsg)
                raise OSError(errmsg)
            else:
                logger.exception("Setting up Gromacs command {0!r} raised an exception.".format(self.command_name))
                raise
        logger.debug(p.command_string)
        return p

Response: Returns a special Popen instance with input.


Instruction:
Can you implement a function in Python 3 that
transforms arguments and return them as a list suitable for Popen.

Response:
def transform_args(self, *args, **kwargs):
        """Transform arguments and return them as a list suitable for Popen."""
        options = []
        for option,value in kwargs.items():
            if not option.startswith('-'):
                # heuristic for turning key=val pairs into options
                # (fails for commands such as 'find' -- then just use args)
                if len(option) == 1:
                    option = '-' + option         # POSIX style
                else:
                    option = '--' + option        # GNU option
            if value is True:
                options.append(option)
                continue
            elif value is False:
                raise ValueError('A False value is ambiguous for option {0!r}'.format(option))

            if option[:2] == '--':
                options.append(option + '=' + str(value))    # GNU option
            else:
                options.extend((option, str(value)))         # POSIX style
        return options + list(args)


Instruction:
Can you create a Python 3 function that
prints help ; same as using? in IPython. long = True also gives call signature.

Response:
def help(self, long=False):
        """Print help; same as using ``?`` in ``ipython``. long=True also gives call signature."""
        print("\ncommand: {0!s}\n\n".format(self.command_name))
        print(self.__doc__)
        if long:
            print("\ncall method: command():\n")
            print(self.__call__.__doc__)


Instruction:
Write a Python 3 function for
combining the default values and the supplied values.

Response:
def _combine_arglist(self, args, kwargs):
        """Combine the default values and the supplied values."""
        gmxargs = self.gmxargs.copy()
        gmxargs.update(self._combineargs(*args, **kwargs))
        return (), gmxargs


Instruction:
Create a Python 3 function to
combine the arguments of the command line.

Response:
def _combineargs(self, *args, **kwargs):
        """Add switches as 'options' with value True to the options dict."""
        d = {arg: True for arg in args}   # switches are kwargs with value True
        d.update(kwargs)
        return d


Instruction:
How would you code a function in Python 3 to
build a list of arguments from the dictionary.

Response:
def _build_arg_list(self, **kwargs):
        """Build list of arguments from the dict; keys must be valid  gromacs flags."""
        arglist = []
        for flag, value in kwargs.items():
            # XXX: check flag against allowed values
            flag = str(flag)
            if flag.startswith('_'):
                flag = flag[1:]                 # python-illegal keywords are '_'-quoted
            if not flag.startswith('-'):
                flag = '-' + flag               # now flag is guaranteed to start with '-'
            if value is True:
                arglist.append(flag)            # simple command line flag
            elif value is False:
                if flag.startswith('-no'):
                    # negate a negated flag ('noX=False' --> X=True --> -X ... but who uses that?)
                    arglist.append('-' + flag[3:])
                else:
                    arglist.append('-no' + flag[1:])  # gromacs switches booleans by prefixing 'no'
            elif value is None:
                pass                            # ignore flag = None
            else:
                try:
                    arglist.extend([flag] + value) # option with value list
                except TypeError:
                    arglist.extend([flag, value])  # option with single value
        return list(map(str, arglist))


Instruction:
Given the following Python 3 function, write the documentation
def _run_command(self,*args,**kwargs):
        result, p = super(GromacsCommand, self)._run_command(*args, **kwargs)
        self.check_failure(result, command_string=p.command_string)
        return result, p

Response: Execute the gromacs command ; see the docs for __call__.


Instruction:
How would you explain what the following Python 3 function does
def _commandline(self, *args, **kwargs):
        if(self.driver is not None):
            return [self.driver, self.command_name] + self.transform_args(*args, **kwargs)
        return [self.command_name] + self.transform_args(*args, **kwargs)

Response: Returns the command line as a list. Inserts driver if present


Instruction:
Write a Python 3 script to
combine arguments and turn them into gromacs tool arguments.

Response:
def transform_args(self,*args,**kwargs):
        """Combine arguments and turn them into gromacs tool arguments."""
        newargs = self._combineargs(*args, **kwargs)
        return self._build_arg_list(**newargs)


Instruction:
Can you create a Python 3 function that
extracts standard gromacs docstrings from the command line and return them as a string.

Response:
def _get_gmx_docs(self):
        """Extract standard gromacs doc

        Extract by running the program and chopping the header to keep from
        'DESCRIPTION' onwards.
        """
        if self._doc_cache is not None:
            return self._doc_cache

        try:
            logging.disable(logging.CRITICAL)
            rc, header, docs = self.run('h', stdout=PIPE, stderr=PIPE, use_input=False)
        except:
            logging.critical("Invoking command {0} failed when determining its doc string. Proceed with caution".format(self.command_name))
            self._doc_cache = "(No Gromacs documentation available)"
            return self._doc_cache
        finally:
            # ALWAYS restore logging...
            logging.disable(logging.NOTSET)

        # The header is on STDOUT and is ignored. The docs are read from STDERR in GMX 4.
        m = re.match(self.doc_pattern, docs, re.DOTALL)

        if m is None:
            # In GMX 5, the opposite is true (Grrr)
            m = re.match(self.doc_pattern, header, re.DOTALL)
            if m is None:
                self._doc_cache = "(No Gromacs documentation available)"
                return self._doc_cache

        self._doc_cache = m.group('DOCS')
        return self._doc_cache


Instruction:
Explain what the following Python 3 code does
def communicate(self, use_input=True):
        if use_input:
            return super(PopenWithInput, self).communicate(self.input)
        else:
            return super(PopenWithInput, self).communicate()

Response: Run the command using the input that was set up on __init__.


Instruction:
Explain what the following Python 3 code does
def autoconvert(s):
    if type(s) is not str:
        return s
    for converter in int, float, str:   # try them in increasing order of lenience
        try:
            s = [converter(i) for i in s.split()]
            if len(s) == 1:
                return s[0]
            else:
                return numpy.array(s)
        except (ValueError, AttributeError):
            pass
    raise ValueError("Failed to autoconvert {0!r}".format(s))

Response: Convert input to a numerical type if possible.


Instruction:
How would you explain what the following Python 3 function does
def openany(datasource, mode='rt', reset=True):
    stream = anyopen(datasource, mode=mode, reset=reset)
    try:
        yield stream
    finally:
        stream.close()

Response: A context manager for opening any file or stream.


Instruction:
Make a summary of the following Python 3 code
def anyopen(datasource, mode='rt', reset=True):
    handlers = {'bz2': bz2_open, 'gz': gzip.open, '': open}

    if mode.startswith('r'):
        if isstream(datasource):
            stream = datasource
            try:
                filename = str(stream.name)  # maybe that does not always work?
            except AttributeError:
                filename = "<stream>"
            if reset:
                try:
                    stream.reset()
                except (AttributeError, IOError):
                    try:
                        stream.seek(0)
                    except (AttributeError, IOError):
                        warnings.warn("Stream {0}: not guaranteed to be at the beginning."
                                      "".format(filename),
                                      category=StreamWarning)
        else:
            stream = None
            filename = datasource
            for ext in ('bz2', 'gz', ''):  # file == '' should be last
                openfunc = handlers[ext]
                stream = _get_stream(datasource, openfunc, mode=mode)
                if stream is not None:
                    break
            if stream is None:
                raise IOError(errno.EIO, "Cannot open file or stream in mode={mode!r}.".format(**vars()), repr(filename))
    elif mode.startswith('w') or mode.startswith('a'):  # append 'a' not tested...
        if isstream(datasource):
            stream = datasource
            try:
                filename = str(stream.name)  # maybe that does not always work?
            except AttributeError:
                filename = "<stream>"
        else:
            stream = None
            filename = datasource
            name, ext = os.path.splitext(filename)
            if ext.startswith('.'):
                ext = ext[1:]
            if not ext in ('bz2', 'gz'):
                ext = ''  # anything else but bz2 or gz is just a normal file
            openfunc = handlers[ext]
            stream = openfunc(datasource, mode=mode)
            if stream is None:
                raise IOError(errno.EIO, "Cannot open file or stream in mode={mode!r}.".format(**vars()), repr(filename))
    else:
        raise NotImplementedError("Sorry, mode={mode!r} is not implemented for {datasource!r}".format(**vars()))
    try:
        stream.name = filename
    except (AttributeError, TypeError):
        pass  # can't set name (e.g. cStringIO.StringIO)
    return stream

Response: Open a file or a stream.


Instruction:
Here you have a function in Python 3, explain what it does
def _get_stream(filename, openfunction=open, mode='r'):
    try:
        stream = openfunction(filename, mode=mode)
    except (IOError, OSError) as err:
        # An exception might be raised due to two reasons, first the openfunction is unable to open the file, in this
        # case we have to ignore the error and return None. Second is when openfunction can't open the file because
        # either the file isn't there or the permissions don't allow access.
        if errno.errorcode[err.errno] in ['ENOENT', 'EACCES']:
            six.reraise(*sys.exc_info())
        return None
    if mode.startswith('r'):
        # additional check for reading (eg can we uncompress) --- is this needed?
        try:
            stream.readline()
        except IOError:
            stream.close()
            stream = None
        except:
            stream.close()
            raise
        else:
            stream.close()
            stream = openfunction(filename, mode=mode)
    return stream

Response: Return open stream if filename can be opened with openfunction or else None.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def hasmethod(obj, m):
    return hasattr(obj, m) and callable(getattr(obj, m))

Response: Return True if object *obj* contains the method m.


Instruction:
Can you implement a function in Python 3 that
detects if an object is a stream.

Response:
def isstream(obj):
    """Detect if `obj` is a stream.

    We consider anything a stream that has the methods

    - ``close()``

    and either set of the following

    - ``read()``, ``readline()``, ``readlines()``
    - ``write()``, ``writeline()``, ``writelines()``

    :Arguments:
      *obj*
          stream or str

    :Returns:
      *bool*, ``True`` if `obj` is a stream, ``False`` otherwise

    .. SeeAlso::
       :mod:`io`

    .. versionadded:: 0.7.1
    """
    signature_methods = ("close",)
    alternative_methods = (
        ("read", "readline", "readlines"),
        ("write", "writeline", "writelines"))

    # Must have ALL the signature methods
    for m in signature_methods:
        if not hasmethod(obj, m):
            return False
    # Must have at least one complete set of alternative_methods
    alternative_results = [
        numpy.all([hasmethod(obj, m) for m in alternatives])
        for alternatives in alternative_methods]
    return numpy.any(alternative_results)


Instruction:
Implement a Python 3 function for
converting between 1 - letter amino acid codes and 3 - letter amino acid codes.

Response:
def convert_aa_code(x):
    """Converts between 3-letter and 1-letter amino acid codes."""
    if len(x) == 1:
        return amino_acid_codes[x.upper()]
    elif len(x) == 3:
        return inverse_aa_codes[x.upper()]
    else:
        raise ValueError("Can only convert 1-letter or 3-letter amino acid codes, "
                         "not %r" % x)


Instruction:
Can you generate the documentation for the following Python 3 function
def realpath(*args):
    if None in args:
        return None
    return os.path.realpath(
        os.path.expandvars(os.path.expanduser(os.path.join(*args))))

Response: Join all args and return the real path rooted at /.


Instruction:
Write a Python 3 script for
finding first filename with a suffix from suffices.

Response:
def find_first(filename, suffices=None):
    """Find first *filename* with a suffix from *suffices*.

    :Arguments:
      *filename*
         base filename; this file name is checked first
      *suffices*
         list of suffices that are tried in turn on the root of *filename*; can contain the
         ext separator (:data:`os.path.extsep`) or not

    :Returns: The first match or ``None``.
    """
    # struct is not reliable as it depends on qscript so now we just try everything...

    root,extension = os.path.splitext(filename)
    if suffices is None:
        suffices = []
    else:
        suffices = withextsep(suffices)
    extensions = [extension] + suffices  # native name is first
    for ext in extensions:
        fn = root + ext
        if os.path.exists(fn):
            return fn
    return None


Instruction:
Can you tell what is the following Python 3 function doing
def withextsep(extensions):
    def dottify(x):
        if x.startswith(os.path.extsep):
            return x
        return os.path.extsep + x
    return [dottify(x) for x in asiterable(extensions)]

Response: Return list of files in which each element is guaranteed to start with the given extensions.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def iterable(obj):
    if isinstance(obj, string_types):
        return False    # avoid iterating over characters of a string
    if hasattr(obj, 'next'):
        return True    # any iterator will do
    try:
        len(obj)       # anything else that might work
    except TypeError:
        return False
    return True

Response: Returns True if obj can be iterated over and is not a string.


Instruction:
How would you explain what the following Python 3 function does
def unlink_f(path):
    try:
        os.unlink(path)
    except OSError as err:
        if err.errno != errno.ENOENT:
            raise

Response: Unlink a file but do not complain if file does not exist.


Instruction:
Can you tell what is the following Python 3 function doing
def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as err:
        if err.errno != errno.EEXIST:
            raise

Response: Create a directory path with subdirs but do not complain if it exists.


Instruction:
Create a Python 3 function for
concatenating files f and write to o

Response:
def cat(f=None, o=None):
    """Concatenate files *f*=[...] and write to *o*"""
    # need f, o to be compatible with trjcat and eneconv
    if f is None or o is None:
        return
    target = o
    infiles = asiterable(f)
    logger.debug("cat {0!s} > {1!s} ".format(" ".join(infiles), target))
    with open(target, 'w') as out:
        rc = subprocess.call(['cat'] + infiles, stdout=out)
    if rc != 0:
        msg = "failed with return code {0:d}: cat {1!r} > {2!r} ".format(rc, " ".join(infiles), target)
        logger.exception(msg)
        raise OSError(errno.EIO, msg, target)


Instruction:
Here you have a function in Python 3, explain what it does
def activate_subplot(numPlot):
    # see http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg07156.html
    from pylab import gcf, axes
    numPlot -= 1  # index is 0-based, plots are 1-based
    return axes(gcf().get_axes()[numPlot])

Response: Make subplot numPlot active on the canvas.


Instruction:
Explain what the following Python 3 code does
def remove_legend(ax=None):
    from pylab import gca, draw
    if ax is None:
        ax = gca()
    ax.legend_ = None
    draw()

Response: Remove legend for axes or gca.


Instruction:
Can you tell what is the following Python 3 function doing
def number_pdbs(*args, **kwargs):

    format = kwargs.pop('format', "%(num)04d")
    name_format = "%(prefix)s" + format +".%(suffix)s"

    for f in itertools.chain.from_iterable(map(glob.glob, args)):
        m = NUMBERED_PDB.search(f)
        if m is None:
            continue
        num = int(m.group('NUMBER'))
        prefix = m.group('PREFIX')
        suffix = m.group('SUFFIX')
        newname = name_format % vars()
        logger.info("Renaming {f!r} --> {newname!r}".format(**vars()))
        try:
            os.rename(f, newname)
        except OSError:
            logger.exception("renaming failed")

Response: Rename pdbs x1. pdb... x345. pdb... x0345. pdb... x0345. pdb... x01. pdb... x0345. pdb... x01. pdb... x0345. pdb... x01. pdb... x0345. pdb... x01. pdb... x01. pdb... x01. pdb... x0345. pdb... x01. pdb... x01. pdb... x01. pdb... x01. pdb


Instruction:
Write a Python 3 function that can
initialize the current filename of the object.

Response:
def _init_filename(self, filename=None, ext=None):
        """Initialize the current filename :attr:`FileUtils.real_filename` of the object.

        Bit of a hack.

        - The first invocation must have ``filename != None``; this will set a
          default filename with suffix :attr:`FileUtils.default_extension`
          unless another one was supplied.

        - Subsequent invocations either change the filename accordingly or
          ensure that the default filename is set with the proper suffix.

        """

        extension = ext or self.default_extension
        filename = self.filename(filename, ext=extension, use_my_ext=True, set_default=True)
        #: Current full path of the object for reading and writing I/O.
        self.real_filename = os.path.realpath(filename)


Instruction:
Implement a function in Python 3 to
supply a filename for the class object.

Response:
def filename(self,filename=None,ext=None,set_default=False,use_my_ext=False):
        """Supply a file name for the class object.

        Typical uses::

           fn = filename()             ---> <default_filename>
           fn = filename('name.ext')   ---> 'name'
           fn = filename(ext='pickle') ---> <default_filename>'.pickle'
           fn = filename('name.inp','pdf') --> 'name.pdf'
           fn = filename('foo.pdf',ext='png',use_my_ext=True) --> 'foo.pdf'

        The returned filename is stripped of the extension
        (``use_my_ext=False``) and if provided, another extension is
        appended. Chooses a default if no filename is given.

        Raises a ``ValueError`` exception if no default file name is known.

        If ``set_default=True`` then the default filename is also set.

        ``use_my_ext=True`` lets the suffix of a provided filename take
        priority over a default ``ext`` tension.

        .. versionchanged:: 0.3.1
           An empty string as *ext* = "" will suppress appending an extension.
        """
        if filename is None:
            if not hasattr(self,'_filename'):
                self._filename = None        # add attribute to class
            if self._filename:
                filename = self._filename
            else:
                raise ValueError("A file name is required because no default file name was defined.")
            my_ext = None
        else:
            filename, my_ext = os.path.splitext(filename)
            if set_default:                  # replaces existing default file name
                self._filename = filename
        if my_ext and use_my_ext:
            ext = my_ext
        if ext is not None:
            if ext.startswith(os.extsep):
                ext = ext[1:]  # strip a dot to avoid annoying mistakes
            if ext != "":
                filename = filename + os.extsep + ext
        return filename


Instruction:
Can you tell what is the following Python 3 function doing
def check_file_exists(self, filename, resolve='exception', force=None):
        def _warn(x):
            msg = "File {0!r} already exists.".format(x)
            logger.warn(msg)
            warnings.warn(msg)
            return True
        def _raise(x):
            msg = "File {0!r} already exists.".format(x)
            logger.error(msg)
            raise IOError(errno.EEXIST, x, msg)
        solutions = {'ignore': lambda x: False,      # file exists, but we pretend that it doesn't
                     'indicate': lambda x: True,     # yes, file exists
                     'warn': _warn,
                     'warning': _warn,
                     'exception': _raise,
                     'raise': _raise,
                     }

        if force is True:
            resolve = 'ignore'
        elif force is False:
            resolve = 'exception'

        if not os.path.isfile(filename):
            return False
        else:
            return solutions[resolve](filename)

Response: Check if a file exists.


Instruction:
Can you generate the documentation for the following Python 3 function
def infix_filename(self, name, default, infix, ext=None):
        if name is None:
            p, oldext = os.path.splitext(default)
            if ext is None:
                ext = oldext
            if ext.startswith(os.extsep):
                ext = ext[1:]
            name = self.filename(p+infix, ext=ext)
        return name

Response: Returns the filename of the infix file.


Instruction:
Explain what the following Python 3 code does
def strftime(self, fmt="%d:%H:%M:%S"):
        substitutions = {
            "%d": str(self.days),
            "%H": "{0:02d}".format(self.dhours),
            "%h": str(24*self.days + self.dhours),
            "%M": "{0:02d}".format(self.dminutes),
            "%S": "{0:02d}".format(self.dseconds),
            }
        s = fmt
        for search, replacement in substitutions.items():
            s = s.replace(search, replacement)
        return s

Response:
Primitive string formatter.

        The only directives understood are the following:
          ============   ==========================
          Directive      meaning
          ============   ==========================
          %d             day as integer
          %H             hour  [00-23]
          %h             hours including days
          %M             minute as integer [00-59]
          %S             second as integer [00-59]
          ============   ==========================


Instruction:
Can you tell what is the following Python 3 function doing
def start_logging(logfile="gromacs.log"):
    from . import log
    log.create("gromacs", logfile=logfile)
    logging.getLogger("gromacs").info("GromacsWrapper %s STARTED logging to %r",
                                      __version__, logfile)

Response: Start logging of messages to file and console.


Instruction:
Can you write a function in Python 3 where it
stops logging to logfile and console.

Response:
def stop_logging():
    """Stop logging to logfile and console."""
    from . import log
    logger = logging.getLogger("gromacs")
    logger.info("GromacsWrapper %s STOPPED logging", get_version())
    log.clear_handlers(logger)


Instruction:
How would you implement a function in Python 3 that
sets the : meth:`warnings. simplefilter to action.

Response:
def filter_gromacs_warnings(action, categories=None):
    """Set the :meth:`warnings.simplefilter` to *action*.

    *categories* must be a list of warning classes or strings.
    ``None`` selects the defaults,  :data:`gromacs.less_important_warnings`.
    """

    if categories is None:
        categories = less_important_warnings
    for c in categories:
        try:
            w = globals()[c]
        except KeyError:
            w = c
        if not issubclass(w, Warning):
            raise TypeError("{0!r} is neither a Warning nor the name of a Gromacs warning.".format(c))
        warnings.simplefilter(action, category=w)


Instruction:
Given the following Python 3 function, write the documentation
def tool_factory(clsname, name, driver, base=GromacsCommand):
    clsdict = {
        'command_name': name,
        'driver': driver,
        '__doc__': property(base._get_gmx_docs)
    }
    return type(clsname, (base,), clsdict)

Response: Factory for GromacsCommand derived types.


Instruction:
Make a summary of the following Python 3 code
def find_executables(path):
    execs = []
    for exe in os.listdir(path):
        fullexe = os.path.join(path, exe)
        if (os.access(fullexe, os.X_OK) and not os.path.isdir(fullexe) and
             exe not in ['GMXRC', 'GMXRC.bash', 'GMXRC.csh', 'GMXRC.zsh',
                         'demux.pl', 'xplor2gmx.pl']):
            execs.append(exe)
    return execs

Response: Find executables in a directory excluding some know commands.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def load_v5_tools():
    logger.debug("Loading 2018/2016/5.x tools...")

    drivers = config.get_tool_names()

    if len(drivers) == 0 and 'GMXBIN' in os.environ:
        drivers = find_executables(os.environ['GMXBIN'])

    if len(drivers) == 0 or len(drivers) > 4:
        drivers = ['gmx', 'gmx_d', 'gmx_mpi', 'gmx_mpi_d']

    append = config.cfg.getboolean('Gromacs', 'append_suffix', fallback=True)

    tools = {}
    for driver in drivers:
        suffix = driver.partition('_')[2]
        try:
            out = subprocess.check_output([driver, '-quiet', 'help',
                                           'commands'])
            for line in out.splitlines()[5:-1]:
                line = str(line.decode('ascii'))   # Python 3: byte string -> str, Python 2: normal string
                if line[4] != ' ':
                    name = line[4:line.index(' ', 4)]
                    fancy = make_valid_identifier(name)
                    if suffix and append:
                        fancy = '{0!s}_{1!s}'.format(fancy, suffix)
                    tools[fancy] = tool_factory(fancy, name, driver)
        except (subprocess.CalledProcessError, OSError):
            pass

    if not tools:
        errmsg = "Failed to load 2018/2016/5.x tools (tried drivers: {})".format(drivers)
        logger.debug(errmsg)
        raise GromacsToolLoadingError(errmsg)
    logger.debug("Loaded {0} v5 tools successfully!".format(len(tools)))
    return tools

Response: Load Gromacs 2018 - 2017 - 5. x tools.


Instruction:
Implement a Python 3 function for
loading Gromacs 4. x tools automatically using some heuristic.

Response:
def load_v4_tools():
    """ Load Gromacs 4.x tools automatically using some heuristic.

    Tries to load tools (1) in configured tool groups (2) and fails back  to
    automatic detection from ``GMXBIN`` (3) then to a prefilled list.

    Also load any extra tool configured in ``~/.gromacswrapper.cfg``

    :return: dict mapping tool names to GromacsCommand classes
    """
    logger.debug("Loading v4 tools...")

    names = config.get_tool_names()

    if len(names) == 0 and 'GMXBIN' in os.environ:
        names = find_executables(os.environ['GMXBIN'])

    if len(names) == 0 or len(names) > len(V4TOOLS) * 4:
        names = list(V4TOOLS)

    names.extend(config.get_extra_tool_names())

    tools = {}
    for name in names:
        fancy = make_valid_identifier(name)
        tools[fancy] = tool_factory(fancy, name, None)

    if not tools:
        errmsg = "Failed to load v4 tools"
        logger.debug(errmsg)
        raise GromacsToolLoadingError(errmsg)
    logger.debug("Loaded {0} v4 tools successfully!".format(len(tools)))
    return tools


Instruction:
Write a Python 3 function for
taking one or more index files and optionally one structure file and returns a new merged index file.

Response:
def merge_ndx(*args):
    """ Takes one or more index files and optionally one structure file and
    returns a path for a new merged index file.

    :param args: index files and zero or one structure file
    :return: path for the new merged index file
    """
    ndxs = []
    struct = None
    for fname in args:
        if fname.endswith('.ndx'):
            ndxs.append(fname)
        else:
            if struct is not None:
                raise ValueError("only one structure file supported")
            struct = fname

    fd, multi_ndx = tempfile.mkstemp(suffix='.ndx', prefix='multi_')
    os.close(fd)
    atexit.register(os.unlink, multi_ndx)

    if struct:
        make_ndx = registry['Make_ndx'](f=struct, n=ndxs, o=multi_ndx)
    else:
        make_ndx = registry['Make_ndx'](n=ndxs, o=multi_ndx)

    _, _, _ = make_ndx(input=['q'], stdout=False, stderr=False)
    return multi_ndx


Instruction:
Can you tell what is the following Python 3 function doing
def read(self, filename=None):
        self._init_filename(filename)

        data = odict()
        with open(self.real_filename) as ndx:
            current_section = None
            for line in ndx:
                line = line.strip()
                if len(line) == 0:
                    continue
                m = self.SECTION.match(line)
                if m:
                    current_section = m.group('name')
                    data[current_section] = []  # can fail if name not legal python key
                    continue
                if current_section is not None:
                    data[current_section].extend(map(int, line.split()))

        super(NDX,self).update(odict([(name, self._transform(atomnumbers))
                                     for name, atomnumbers in data.items()]))

Response: Read and parse index file filename *filename*.


Instruction:
Create a Python 3 function for
writing the index file to filename or overwrite the file that the index was read from.

Response:
def write(self, filename=None, ncol=ncol, format=format):
        """Write index file to *filename* (or overwrite the file that the index was read from)"""
        with open(self.filename(filename, ext='ndx'), 'w') as ndx:
            for name in self:
                atomnumbers = self._getarray(name)  # allows overriding
                ndx.write('[ {0!s} ]\n'.format(name))
                for k in range(0, len(atomnumbers), ncol):
                    line = atomnumbers[k:k+ncol].astype(int)   # nice formatting in ncol-blocks
                    n = len(line)
                    ndx.write((" ".join(n*[format])+'\n') % tuple(line))
                ndx.write('\n')


Instruction:
Can you tell what is the following Python 3 function doing
def ndxlist(self):
        return [{'name': name, 'natoms': len(atomnumbers), 'nr': nr+1} for
                nr,(name,atomnumbers) in enumerate(self.items())]

Response: Return a list of all the n - dimensional group names and numbers in the current cbook.


Instruction:
Can you create a Python 3 function that
returns an index group that contains atoms from all groupnames.

Response:
def join(self, *groupnames):
        """Return an index group that contains atoms from all  *groupnames*.

        The method will silently ignore any groups that are not in the
        index.

        **Example**

        Always make a solvent group from water and ions, even if not
        all ions are present in all simulations::

           I['SOLVENT'] = I.join('SOL', 'NA+', 'K+', 'CL-')
        """
        return self._sum([self[k] for k in groupnames if k in self])


Instruction:
Implement a Python 3 function for
creating a 1D array where masks jumps > threshold and other is None.

Response:
def break_array(a, threshold=numpy.pi, other=None):
    """Create a array which masks jumps >= threshold.

    Extra points are inserted between two subsequent values whose
    absolute difference differs by more than threshold (default is
    pi).

    Other can be a secondary array which is also masked according to
    *a*.

    Returns (*a_masked*, *other_masked*) (where *other_masked* can be
    ``None``)
    """
    assert len(a.shape) == 1, "Only 1D arrays supported"

    if other is not None and a.shape != other.shape:
        raise ValueError("arrays must be of identical shape")

    # jump occurs after the index in break
    breaks = numpy.where(numpy.abs(numpy.diff(a)) >= threshold)[0]
    # insert a blank after
    breaks += 1

    # is this needed?? -- no, but leave it here as a reminder
    #f2 = numpy.diff(a, 2)
    #up = (f2[breaks - 1] >= 0)  # >0: up, <0: down
    # sort into up and down breaks:
    #breaks_up = breaks[up]
    #breaks_down = breaks[~up]

    # new array b including insertions for all the breaks
    m = len(breaks)
    b = numpy.empty((len(a) + m))
    # calculate new indices for breaks in b, taking previous insertions into account
    b_breaks = breaks + numpy.arange(m)
    mask =  numpy.zeros_like(b, dtype=numpy.bool)
    mask[b_breaks] = True
    b[~mask] = a
    b[mask] = numpy.NAN

    if other is not None:
        c = numpy.empty_like(b)
        c[~mask] = other
        c[mask] = numpy.NAN
        ma_c = numpy.ma.array(c, mask=mask)
    else:
        ma_c = None

    return numpy.ma.array(b, mask=mask), ma_c


Instruction:
Create a Python 3 function to
write array to xvg file filename in NXY format.

Response:
def write(self, filename=None):
        """Write array to xvg file *filename* in NXY format.

        .. Note:: Only plain files working at the moment, not compressed.
        """
        self._init_filename(filename)
        with utilities.openany(self.real_filename, 'w') as xvg:
            xvg.write("# xmgrace compatible NXY data file\n"
                      "# Written by gromacs.formats.XVG()\n")
            xvg.write("# :columns: {0!r}\n".format(self.names))
            for xyy in self.array.T:
                xyy.tofile(xvg, sep=" ", format="%-8s")  # quick and dirty ascii output...--no compression!
                xvg.write('\n')


Instruction:
How would you implement a function in Python 3 that
represents data as a masked array.

Response:
def ma(self):
        """Represent data as a masked array.

        The array is returned with column-first indexing, i.e. for a data file with
        columns X Y1 Y2 Y3 ... the array a will be a[0] = X, a[1] = Y1, ... .

        inf and nan are filtered via :func:`numpy.isfinite`.
        """
        a = self.array
        return numpy.ma.MaskedArray(a, mask=numpy.logical_not(numpy.isfinite(a)))


Instruction:
Create a Python 3 function for
setting and change the parameters for calculations with µs correlation functions.

Response:
def set_correlparameters(self, **kwargs):
        """Set and change the parameters for calculations with  correlation functions.

        The parameters persist until explicitly changed.

        :Keywords:
           *nstep*
               only process every *nstep* data point to speed up the FFT; if
               left empty a default is chosen that produces roughly 25,000 data
               points (or whatever is set in *ncorrel*)
           *ncorrel*
               If no *nstep* is supplied, aim at using *ncorrel* data points for
               the FFT; sets :attr:`XVG.ncorrel` [25000]
           *force*
               force recalculating correlation data even if cached values are
               available
           *kwargs*
               see :func:`numkit.timeseries.tcorrel` for other options

        .. SeeAlso: :attr:`XVG.error` for details and references.
        """
        self.ncorrel = kwargs.pop('ncorrel', self.ncorrel) or 25000
        nstep = kwargs.pop('nstep', None)
        if nstep is None:
            # good step size leads to ~25,000 data points
            nstep = len(self.array[0])/float(self.ncorrel)
            nstep = int(numpy.ceil(nstep))  # catch small data sets
        kwargs['nstep'] = nstep
        self.__correlkwargs.update(kwargs)  # only contains legal kw for numkit.timeseries.tcorrel or force
        return self.__correlkwargs


Instruction:
Given the following Python 3 function, write the documentation
def parse(self, stride=None):
        if stride is None:
            stride = self.stride
        self.corrupted_lineno = []
        irow  = 0  # count rows of data
        # cannot use numpy.loadtxt() because xvg can have two types of 'comment' lines
        with utilities.openany(self.real_filename) as xvg:
            rows = []
            ncol = None
            for lineno,line in enumerate(xvg):
                line = line.strip()
                if len(line) == 0:
                    continue
                if "label" in line and "xaxis" in line:
                        self.xaxis = line.split('"')[-2]
                if "label" in line and "yaxis" in line:
                        self.yaxis = line.split('"')[-2]
                if line.startswith("@ legend"):
                                        if not "legend" in self.metadata: self.metadata["legend"] = []
                                        self.metadata["legend"].append(line.split("legend ")[-1])
                if line.startswith("@ s") and "subtitle" not in line:
                                        name = line.split("legend ")[-1].replace('"','').strip()
                                        self.names.append(name)
                if line.startswith(('#', '@')) :
                                        continue
                if line.startswith('&'):
                    raise NotImplementedError('{0!s}: Multi-data not supported, only simple NXY format.'.format(self.real_filename))
                # parse line as floats
                try:
                    row = [float(el) for el in line.split()]
                except:
                    if self.permissive:
                        self.logger.warn("%s: SKIPPING unparsable line %d: %r",
                                         self.real_filename, lineno+1, line)
                        self.corrupted_lineno.append(lineno+1)
                        continue
                    self.logger.error("%s: Cannot parse line %d: %r",
                                      self.real_filename, lineno+1, line)
                    raise
                # check for same number of columns as in previous step
                if ncol is not None and len(row) != ncol:
                    if self.permissive:
                        self.logger.warn("%s: SKIPPING line %d with wrong number of columns: %r",
                                         self.real_filename, lineno+1, line)
                        self.corrupted_lineno.append(lineno+1)
                        continue
                    errmsg = "{0!s}: Wrong number of columns in line {1:d}: {2!r}".format(self.real_filename, lineno+1, line)
                    self.logger.error(errmsg)
                    raise IOError(errno.ENODATA, errmsg, self.real_filename)
                # finally: a good line
                if irow % stride == 0:
                    ncol = len(row)
                    rows.append(row)
                irow += 1
        try:
            self.__array = numpy.array(rows).transpose()    # cache result
        except:
            self.logger.error("%s: Failed reading XVG file, possibly data corrupted. "
                              "Check the last line of the file...", self.real_filename)
            raise
        finally:
            del rows

Response: Read and cache the file as a numpy array.


Instruction:
Implement a Python 3 function for
plotting the xvg file data.

Response:
def plot(self, **kwargs):
        """Plot xvg file data.

        The first column of the data is always taken as the abscissa
        X. Additional columns are plotted as ordinates Y1, Y2, ...

        In the special case that there is only a single column then this column
        is plotted against the index, i.e. (N, Y).

        :Keywords:
          *columns* : list
               Select the columns of the data to be plotted; the list
               is used as a numpy.array extended slice. The default is
               to use all columns. Columns are selected *after* a transform.
          *transform* : function
               function ``transform(array) -> array`` which transforms
               the original array; must return a 2D numpy array of
               shape [X, Y1, Y2, ...] where X, Y1, ... are column
               vectors.  By default the transformation is the
               identity [``lambda x: x``].
          *maxpoints* : int
               limit the total number of data points; matplotlib has issues processing
               png files with >100,000 points and pdfs take forever to display. Set to
               ``None`` if really all data should be displayed. At the moment we simply
               decimate the data at regular intervals. [10000]
          *method*
               method to decimate the data to *maxpoints*, see :meth:`XVG.decimate`
               for details
          *color*
               single color (used for all plots); sequence of colors
               (will be repeated as necessary); or a matplotlib
               colormap (e.g. "jet", see :mod:`matplotlib.cm`). The
               default is to use the :attr:`XVG.default_color_cycle`.
          *ax*
               plot into given axes or create new one if ``None`` [``None``]
          *kwargs*
               All other keyword arguments are passed on to :func:`matplotlib.pyplot.plot`.

        :Returns:
          *ax*
               axes instance
        """
        columns = kwargs.pop('columns', Ellipsis)         # slice for everything
        maxpoints = kwargs.pop('maxpoints', self.maxpoints_default)
        transform = kwargs.pop('transform', lambda x: x)  # default is identity transformation
        method = kwargs.pop('method', "mean")
        ax = kwargs.pop('ax', None)

        if columns is Ellipsis or columns is None:
            columns = numpy.arange(self.array.shape[0])
        if len(columns) == 0:
            raise MissingDataError("plot() needs at least one column of data")

        if len(self.array.shape) == 1 or self.array.shape[0] == 1:
            # special case: plot against index; plot would do this automatically but
            # we'll just produce our own xdata and pretend that this was X all along
            a = numpy.ravel(self.array)
            X = numpy.arange(len(a))
            a = numpy.vstack((X, a))
            columns = [0] + [c+1 for c in columns]
        else:
            a = self.array

        color = kwargs.pop('color', self.default_color_cycle)
        try:
            cmap = matplotlib.cm.get_cmap(color)
            colors = cmap(matplotlib.colors.Normalize()(numpy.arange(len(columns[1:]), dtype=float)))
        except TypeError:
            colors = cycle(utilities.asiterable(color))

        if ax is None:
            ax = plt.gca()

        # (decimate/smooth o slice o transform)(array)
        a = self.decimate(method, numpy.asarray(transform(a))[columns], maxpoints=maxpoints)

        # now deal with infs, nans etc AFTER all transformations (needed for plotting across inf/nan)
        ma = numpy.ma.MaskedArray(a, mask=numpy.logical_not(numpy.isfinite(a)))

        # finally plot (each column separately to catch empty sets)
        for column, color in zip(range(1,len(columns)), colors):
            if len(ma[column]) == 0:
                warnings.warn("No data to plot for column {column:d}".format(**vars()), category=MissingDataWarning)
            kwargs['color'] = color
            ax.plot(ma[0], ma[column], **kwargs)   # plot all other columns in parallel
        return ax


Instruction:
Can you write a function in Python 3 where it
plots data like XVG. plot with the range of all data shown.

Response:
def plot_coarsened(self, **kwargs):
        """Plot data like :meth:`XVG.plot` with the range of **all** data shown.

        Data are reduced to *maxpoints* (good results are obtained
        with low values such as 100) and the actual range of observed
        data is plotted as a translucent error band around the mean.

        Each column in *columns* (except the abscissa, i.e. the first
        column) is decimated (with :meth:`XVG.decimate`) and the range
        of data is plotted alongside the mean using
        :meth:`XVG.errorbar` (see for arguments). Additional
        arguments:

        :Kewords:
           *maxpoints*
                number of points (bins) to coarsen over
           *color*
                single color (used for all plots); sequence of colors
                (will be repeated as necessary); or a matplotlib
                colormap (e.g. "jet", see :mod:`matplotlib.cm`). The
                default is to use the :attr:`XVG.default_color_cycle`.
           *method*
                Method to coarsen the data. See :meth:`XVG.decimate`

        The *demean* keyword has no effect as it is required to be ``True``.

        .. SeeAlso:: :meth:`XVG.plot`, :meth:`XVG.errorbar` and :meth:`XVG.decimate`
        """
        ax = kwargs.pop('ax', None)
        columns = kwargs.pop('columns', Ellipsis)         # slice for everything
        if columns is Ellipsis or columns is None:
            columns = numpy.arange(self.array.shape[0])
        if len(columns) < 2:
            raise MissingDataError("plot_coarsened() assumes that there is at least one column "
                                   "of data for the abscissa and one or more for the ordinate.")

        color = kwargs.pop('color', self.default_color_cycle)
        try:
            cmap = matplotlib.cm.get_cmap(color)
            colors = cmap(matplotlib.colors.Normalize()(numpy.arange(len(columns[1:]), dtype=float)))
        except TypeError:
            colors = cycle(utilities.asiterable(color))

        if ax is None:
            ax = plt.gca()

        t = columns[0]
        kwargs['demean'] = True
        kwargs['ax'] = ax
        for column, color in zip(columns[1:], colors):
            kwargs['color'] = color
            self.errorbar(columns=[t, column, column], **kwargs)
        return ax


Instruction:
How would you implement a function in Python 3 that
plots an errorbar plot for a single time series with errors.

Response:
def errorbar(self, **kwargs):
        """errorbar plot for a single time series with errors.

        Set *columns* keyword to select [x, y, dy] or [x, y, dx, dy],
        e.g. ``columns=[0,1,2]``. See :meth:`XVG.plot` for
        details. Only a single timeseries can be plotted and the user
        needs to select the appropriate columns with the *columns*
        keyword.

        By default, the data are decimated (see :meth:`XVG.plot`) for
        the default of *maxpoints* = 10000 by averaging data in
        *maxpoints* bins.

        x,y,dx,dy data can plotted with error bars in the x- and
        y-dimension (use *filled* = ``False``).

        For x,y,dy use *filled* = ``True`` to fill the region between
        y±dy. *fill_alpha* determines the transparency of the fill
        color. *filled* = ``False`` will draw lines for the error
        bars. Additional keywords are passed to
        :func:`pylab.errorbar`.

        By default, the errors are decimated by plotting the 5% and
        95% percentile of the data in each bin. The percentile can be
        changed with the *percentile* keyword; e.g. *percentile* = 1
        will plot the 1% and 99% perentile (as will *percentile* =
        99).

        The *error_method* keyword can be used to compute errors as
        the root mean square sum (*error_method* = "rms") across each
        bin instead of percentiles ("percentile"). The value of the
        keyword *demean* is applied to the decimation of error data
        alone.

        .. SeeAlso::

           :meth:`XVG.plot` lists keywords common to both methods.
        """
        ax = kwargs.pop('ax', None)
        color = kwargs.pop('color', 'black')
        filled = kwargs.pop('filled', True)
        fill_alpha = kwargs.pop('fill_alpha', 0.2)

        kwargs.setdefault('capsize', 0)
        kwargs.setdefault('elinewidth', 1)
        kwargs.setdefault('ecolor', color)
        kwargs.setdefault('alpha', 0.3)
        kwargs.setdefault('fmt', None)

        columns = kwargs.pop('columns', Ellipsis)         # slice for everything
        maxpoints = kwargs.pop('maxpoints', self.maxpoints_default)
        transform = kwargs.pop('transform', lambda x: x)  # default is identity transformation
        method = kwargs.pop('method', "mean")
        if method != "mean":
            raise NotImplementedError("For errors only method == 'mean' is supported.")
        error_method = kwargs.pop('error_method', "percentile")  # can also use 'rms' and 'error'
        percentile = numpy.abs(kwargs.pop('percentile', 95.))
        demean = kwargs.pop('demean', False)

        # order: (decimate/smooth o slice o transform)(array)
        try:
            data = numpy.asarray(transform(self.array))[columns]
        except IndexError:
            raise MissingDataError("columns {0!r} are not suitable to index the transformed array, possibly not eneough data".format(columns))
        if data.shape[-1] == 0:
            raise MissingDataError("There is no data to be plotted.")
        a = numpy.zeros((data.shape[0], maxpoints), dtype=numpy.float64)
        a[0:2] = self.decimate("mean", data[0:2], maxpoints=maxpoints)
        error_data = numpy.vstack((data[0], data[2:]))
        if error_method == "percentile":
            if percentile > 50:
                upper_per = percentile
                lower_per = 100 - percentile
            else:
                upper_per = 100 - percentile
                lower_per = percentile
            # demean generally does not make sense with the percentiles (but for analysing
            # the regularised data itself we use this as a flag --- see below!)
            upper = a[2:] = self.decimate("percentile", error_data, maxpoints=maxpoints,
                                          per=upper_per, demean=False)[1:]
            lower = self.decimate("percentile", error_data, maxpoints=maxpoints,
                                  per=lower_per, demean=False)[1:]
        else:
            a[2:] = self.decimate(error_method, error_data, maxpoints=maxpoints, demean=demean)[1:]
            lower = None

        # now deal with infs, nans etc AFTER all transformations (needed for plotting across inf/nan)
        ma = numpy.ma.MaskedArray(a, mask=numpy.logical_not(numpy.isfinite(a)))
        if lower is not None:
            mlower = numpy.ma.MaskedArray(lower, mask=numpy.logical_not(numpy.isfinite(lower)))

        # finally plot
        X = ma[0]          # abscissa set separately
        Y = ma[1]
        try:
            kwargs['yerr'] = ma[3]
            kwargs['xerr'] = ma[2]
        except IndexError:
            try:
                kwargs['yerr'] = ma[2]
            except IndexError:
                raise TypeError("Either too few columns selected or data does not have a error column")

        if ax is None:
            ax = plt.gca()

        if filled:
            # can only plot dy
            if error_method == "percentile":
                if demean:
                    # signal that we are looking at percentiles of an observable and not error
                    y1 = mlower[-1]
                    y2 = kwargs['yerr']
                else:
                    # percentiles of real errors (>0)
                    y1 = Y - mlower[-1]
                    y2 = Y + kwargs['yerr']
            else:
                y1 = Y - kwargs['yerr']
                y2 = Y + kwargs['yerr']
            ax.fill_between(X, y1, y2, color=color, alpha=fill_alpha)
        else:
            if error_method == "percentile":
                # errorbars extend to different lengths;
                if demean:
                    kwargs['yerr'] = numpy.vstack((mlower[-1], kwargs['yerr']))
                else:
                    kwargs['yerr'] = numpy.vstack((Y - mlower[-1], Y + kwargs['yerr']))
                try:
                    # xerr only makes sense when the data is a real
                    # error so we don't even bother with demean=?
                    kwargs['xerr'] = numpy.vstack((X - mlower[0], X + kwargs['xerr']))
                except (KeyError, IndexError):
                    pass
            ax.errorbar(X, Y, **kwargs)

        # clean up args for plot
        for kw in "yerr", "xerr", "capsize", "ecolor", "elinewidth", "fmt":
            kwargs.pop(kw, None)
        kwargs['alpha'] = 1.0

        ax.plot(X, Y, color=color, **kwargs)

        return ax


Instruction:
Can you create a Python 3 function that
decimates data in a given number of data points.

Response:
def decimate(self, method, a, maxpoints=10000, **kwargs):
        """Decimate data *a* to *maxpoints* using *method*.

        If *a* is a 1D array then it is promoted to a (2, N) array
        where the first column simply contains the index.

        If the array contains fewer than *maxpoints* points or if
        *maxpoints* is ``None`` then it is returned as it is. The
        default for *maxpoints* is 10000.

        Valid values for the reduction *method*:

          * "mean", uses :meth:`XVG.decimate_mean` to coarse grain by
            averaging the data in bins along the time axis

          * "circmean", uses :meth:`XVG.decimate_circmean` to coarse
            grain by calculating the circular mean of the data in bins
            along the time axis. Use additional keywords *low* and
            *high* to set the limits. Assumes that the data are in
            degrees.

          * "min" and "max* select the extremum in each bin

          * "rms", uses :meth:`XVG.decimate_rms` to coarse grain by
            computing the root mean square sum of the data in bins
            along the time axis (for averaging standard deviations and
            errors)

          * "percentile" with keyword *per*: :meth:`XVG.decimate_percentile`
            reduces data in each bin to the percentile *per*

          * "smooth", uses :meth:`XVG.decimate_smooth` to subsample
            from a smoothed function (generated with a running average
            of the coarse graining step size derived from the original
            number of data points and *maxpoints*)

        :Returns: numpy array ``(M', N')`` from a ``(M', N)`` array
                  with ``M' == M`` (except when ``M == 1``, see above)
                  and ``N' <= N`` (``N'`` is *maxpoints*).
        """
        methods = {'mean': self.decimate_mean,
                   'min': self.decimate_min,
                   'max': self.decimate_max,
                   'smooth': self.decimate_smooth,
                   'rms': self.decimate_rms,
                   'percentile': self.decimate_percentile,
                   'error': self.decimate_error,  # undocumented, not working well
                   'circmean': self.decimate_circmean,
                   }
        if len(a.shape) == 1:
            # add first column as index
            # (probably should do this in class/init anyway...)
            X = numpy.arange(len(a))
            a = numpy.vstack([X, a])
        ny = a.shape[-1]   # assume 1D or 2D array with last dimension varying fastest
        if maxpoints is None or ny <= maxpoints:
            return a
        return methods[method](a, maxpoints, **kwargs)


Instruction:
Implement a Python 3 function for
returning data a * mean - decimated on maxpoints * bins and calculates the weighted average of each bin in each column into maxpoints * bins and returns a new array of the same dimensions as a.

Response:
def decimate_mean(self, a, maxpoints, **kwargs):
        """Return data *a* mean-decimated on *maxpoints*.

        Histograms each column into *maxpoints* bins and calculates
        the weighted average in each bin as the decimated data, using
        :func:`numkit.timeseries.mean_histogrammed_function`. The coarse grained
        time in the first column contains the centers of the histogram
        time.

        If *a* contains <= *maxpoints* then *a* is simply returned;
        otherwise a new array of the same dimensions but with a
        reduced number of  *maxpoints* points is returned.

        .. Note::

           Assumes that the first column is time.

        """
        return self._decimate(numkit.timeseries.mean_histogrammed_function, a, maxpoints, **kwargs)


Instruction:
Can you create a Python 3 function that
returns data a * circmean - decimated on maxpoints * bins and calculates the weighted circular mean in each bin.

Response:
def decimate_circmean(self, a, maxpoints, **kwargs):
        """Return data *a* circmean-decimated on *maxpoints*.

        Histograms each column into *maxpoints* bins and calculates
        the weighted circular mean in each bin as the decimated data,
        using
        :func:`numkit.timeseries.circmean_histogrammed_function`. The
        coarse grained time in the first column contains the centers
        of the histogram time.

        If *a* contains <= *maxpoints* then *a* is simply returned;
        otherwise a new array of the same dimensions but with a
        reduced number of  *maxpoints* points is returned.

        Keywords *low* and *high* can be used to set the
        boundaries. By default they are [-pi, +pi].

        This method returns a **masked** array where jumps are flagged
        by an insertion of a masked point.

        .. Note::

           Assumes that the first column is time and that the data are
           in **degrees**.

        .. Warning::

           Breaking of arrays only works properly with a two-column
           array because breaks are only inserted in the x-column
           (a[0]) where y1 = a[1] has a break.

        """
        a_rad = numpy.vstack((a[0], numpy.deg2rad(a[1:])))
        b = self._decimate(numkit.timeseries.circmean_histogrammed_function, a_rad, maxpoints, **kwargs)
        y_ma, x_ma = break_array(b[1], threshold=numpy.pi, other=b[0])
        v = [y_ma]
        for y in b[2:]:
            v.append(break_array(y, threshold=numpy.pi)[0])
            if v[-1].shape != v[0].shape:
                raise ValueError("y dimensions have different breaks: you MUST deal with them separately")
        return numpy.vstack((x_ma, numpy.rad2deg(v)))


Instruction:
Explain what the following Python 3 code does
def decimate_min(self, a, maxpoints, **kwargs):
        return self._decimate(numkit.timeseries.min_histogrammed_function, a, maxpoints, **kwargs)

Response: Return data *a* min - decimated on maxpoints.


Instruction:
Explain what the following Python 3 code does
def decimate_max(self, a, maxpoints, **kwargs):
        return self._decimate(numkit.timeseries.max_histogrammed_function, a, maxpoints, **kwargs)

Response: Return data *a* max - decimated on maxpoints.


Instruction:
Write a Python 3 function for
returning data a * rms - decimated on maxpoints * bins and calculates the root mean square sum of each bin in each column into maxpoints * bins and returns a new array of the same dimensions as a.

Response:
def decimate_rms(self, a, maxpoints, **kwargs):
        """Return data *a* rms-decimated on *maxpoints*.

        Histograms each column into *maxpoints* bins and calculates
        the root mean square sum in each bin as the decimated data,
        using :func:`numkit.timeseries.rms_histogrammed_function`. The coarse
        grained time in the first column contains the centers of the
        histogram time.

        If *a* contains <= *maxpoints* then *a* is simply returned;
        otherwise a new array of the same dimensions but with a
        reduced number of  *maxpoints* points is returned.

        .. Note::

           Assumes that the first column is time.

        """
        return self._decimate(numkit.timeseries.rms_histogrammed_function, a, maxpoints, **kwargs)


Instruction:
Can you generate the documentation for the following Python 3 function
def decimate_percentile(self, a, maxpoints, **kwargs):
        return self._decimate(numkit.timeseries.percentile_histogrammed_function, a, maxpoints, **kwargs)

Response: Return data *a* percentile - decimated on maxpoints.


Instruction:
Create a Python 3 function for
returning data a * error - decimated on maxpoints * bins and calculates an error estimate in each bin.

Response:
def decimate_error(self, a, maxpoints, **kwargs):
        """Return data *a* error-decimated on *maxpoints*.

        Histograms each column into *maxpoints* bins and calculates an
        error estimate in each bin as the decimated data, using
        :func:`numkit.timeseries.error_histogrammed_function`. The
        coarse grained time in the first column contains the centers
        of the histogram time.

        If *a* contains <= *maxpoints* then *a* is simply returned;
        otherwise a new array of the same dimensions but with a
        reduced number of  *maxpoints* points is returned.

        .. SeeAlso:: :func:`numkit.timeseries.tcorrel`

        .. Note::

           Assumes that the first column is time.

           Does not work very well because often there are too few
           datapoints to compute a good autocorrelation function.

        """
        warnings.warn("Using undocumented decimate_error() is highly EXPERIMENTAL",
                      category=gromacs.exceptions.LowAccuracyWarning)
        return self._decimate(numkit.timeseries.error_histogrammed_function, a,
                              maxpoints, **kwargs)


Instruction:
Can you generate the documentation for the following Python 3 function
def decimate_smooth(self, a, maxpoints, window="flat"):
        ny = a.shape[-1]   # assume 1D or 2D array with last dimension varying fastest
        # reduce size by averaging oover stepsize steps and then just
        # picking every stepsize data points.  (primitive --- can
        # leave out bits at the end or end up with almost twice of
        # maxpoints)
        stepsize = int(ny / maxpoints)
        if stepsize % 2 == 0:
            stepsize += 1  # must be odd for the running average/smoothing window
        out = numpy.empty_like(a)

        # smoothed
        out[0,:] = a[0]
        for i in range(1, a.shape[0]):
            # process columns because smooth() only handles 1D arrays :-p
            out[i,:] = numkit.timeseries.smooth(a[i], stepsize, window=window)

        if maxpoints == self.maxpoints_default:  # only warn if user did not set maxpoints
            warnings.warn("Plot had %d datapoints > maxpoints = %d; decimated to %d regularly "
                          "spaced points with smoothing (%r) over %d steps."
                          % (ny, maxpoints, ny/stepsize, window, stepsize),
                          category=AutoCorrectionWarning)
        return out[..., ::stepsize]

Response: Return a smoothed version of a.