Instruction:
Explain what the following Python 3 code does
def outputs_matching(outputs, patterns):
    '''Get the outputs from a network that match a pattern.

    Parameters
    ----------
    outputs : dict or sequence of (str, theano expression)
        Output expressions to filter for matches. If this is a dictionary, its
        ``items()`` will be processed for matches.
    patterns : sequence of str
        A sequence of glob-style patterns to match against. Any parameter
        matching any pattern in this sequence will be included in the match.

    Yields
    ------
    matches : pair of str, theano expression
        Generates a sequence of (name, expression) pairs. The name is the name
        of the output that matched, and the expression is the symbolic output in
        the network graph.
    '''
    if isinstance(patterns, basestring):
        patterns = (patterns, )
    if isinstance(outputs, dict):
        outputs = outputs.items()
    for name, expr in outputs:
        for pattern in patterns:
            if fnmatch.fnmatch(name, pattern):
                yield name, expr
                break

Response: Get the outputs from a network that match a pattern.


Instruction:
How would you code a function in Python 3 to
get the parameters from a network that match a pattern.

Response:
def params_matching(layers, patterns):
    '''Get the parameters from a network that match a pattern.

    Parameters
    ----------
    layers : list of :class:`theanets.layers.Layer`
        A list of network layers to retrieve parameters from.
    patterns : sequence of str
        A sequence of glob-style patterns to match against. Any parameter
        matching any pattern in this sequence will be included in the match.

    Yields
    ------
    matches : pair of str, theano expression
        Generates a sequence of (name, expression) pairs. The name is the name
        of the parameter that matched, and the expression represents the
        parameter symbolically.
    '''
    if isinstance(patterns, basestring):
        patterns = (patterns, )
    for layer in layers:
        for param in layer.params:
            name = param.name
            for pattern in patterns:
                if fnmatch.fnmatch(name, pattern):
                    yield name, param
                    break


Instruction:
Write a Python 3 script to
construct a common regularizer from a set of keyword arguments.

Response:
def from_kwargs(graph, **kwargs):
    '''Construct common regularizers from a set of keyword arguments.

    Keyword arguments not listed below will be passed to
    :func:`Regularizer.build` if they specify the name of a registered
    :class:`Regularizer`.

    Parameters
    ----------
    graph : :class:`theanets.graph.Network`
        A network graph to regularize.

    regularizers : dict or tuple/list of :class:`Regularizer`, optional
        If this is a list or a tuple, the contents of the list will be returned
        as the regularizers. This is to permit custom lists of regularizers to
        be passed easily.

        If this is a dict, its contents will be added to the other keyword
        arguments passed in.

    rng : int or theano RandomStreams, optional
        If an integer is provided, it will be used to seed the random number
        generators for the dropout or noise regularizers. If a theano
        RandomStreams object is provided, it will be used directly. Defaults to
        13.

    input_dropout : float, optional
        Apply dropout to input layers in the network graph, with this dropout
        rate. Defaults to 0 (no dropout).

    hidden_dropout : float, optional
        Apply dropout to hidden layers in the network graph, with this dropout
        rate. Defaults to 0 (no dropout).

    output_dropout : float, optional
        Apply dropout to the output layer in the network graph, with this
        dropout rate. Defaults to 0 (no dropout).

    input_noise : float, optional
        Apply noise to input layers in the network graph, with this standard
        deviation. Defaults to 0 (no noise).

    hidden_noise : float, optional
        Apply noise to hidden layers in the network graph, with this standard
        deviation. Defaults to 0 (no noise).

    output_noise : float, optional
        Apply noise to the output layer in the network graph, with this
        standard deviation. Defaults to 0 (no noise).

    Returns
    -------
    regs : list of :class:`Regularizer`
        A list of regularizers to apply to the given network graph.
    '''
    if 'regularizers' in kwargs:
        regs = kwargs['regularizers']
        if isinstance(regs, (tuple, list)):
            return regs
        if isinstance(regs, dict):
            kwargs.update(regs)

    regs = []

    rng = kwargs.get('rng', 13)

    def pattern(ls):
        return tuple(l.output_name for l in ls)

    inputs = pattern([l for l in graph.layers if isinstance(l, layers.Input)])
    hiddens = pattern(graph.layers[1:-1])
    outputs = pattern([graph.layers[-1]])

    # create regularizers for different types of canned dropout.
    spec = {inputs: kwargs.get('input_dropout', 0),
            hiddens: kwargs.get('hidden_dropout', 0),
            outputs: kwargs.get('output_dropout', 0)}
    spec.update(kwargs.get('dropout', {}))
    for pattern, w in spec.items():
        if w:
            regs.append(BernoulliDropout(pattern=pattern, weight=w, rng=rng))

    # create regularizers for different types of canned noise.
    spec = {inputs: kwargs.get('input_noise', 0),
            hiddens: kwargs.get('hidden_noise', 0),
            outputs: kwargs.get('output_noise', 0)}
    spec.update(kwargs.get('noise', {}))
    for pattern, w in spec.items():
        if w:
            regs.append(GaussianNoise(pattern=pattern, weight=w, rng=rng))

    # create regularizers based on other keyword arguments.
    for key, value in kwargs.items():
        if Regularizer.is_registered(key):
            if not isinstance(value, dict):
                value = dict(weight=value)
            regs.append(Regularizer.build(key, **value))

    return regs


Instruction:
Can you generate the documentation for the following Python 3 function
def variables(self):
        '''A list of Theano variables used in this loss.'''
        result = [self._target]
        if self._weights is not None:
            result.append(self._weights)
        return result

Response: A list of Theano variables used in this loss.


Instruction:
Can you create a Python 3 function that
builds a Theano expression for computing the accuracy of the graph output.

Response:
def accuracy(self, outputs):
        '''Build a Theano expression for computing the accuracy of graph output.

        Parameters
        ----------
        outputs : dict of Theano expressions
            A dictionary mapping network output names to Theano expressions
            representing the outputs of a computation graph.

        Returns
        -------
        acc : Theano expression
            A Theano expression representing the accuracy of the output compared
            to the target data.
        '''
        output = outputs[self.output_name]
        predict = TT.argmax(output, axis=-1)
        correct = TT.eq(predict, self._target)
        acc = correct.mean()
        if self._weights is not None:
            acc = (self._weights * correct).sum() / self._weights.sum()
        return acc


Instruction:
Explain what the following Python 3 code does
def _scan(self, inputs, outputs, name='scan', step=None, constants=None):
        '''Helper method for defining a basic loop in theano.

        Parameters
        ----------
        inputs : sequence of theano expressions
            Inputs to the scan operation.
        outputs : sequence of output specifiers
            Specifiers for the outputs of the scan operation. This should be a
            sequence containing:
            - None for values that are output by the scan but not tapped as
              inputs,
            - an integer or theano scalar (``ndim == 0``) indicating the batch
              size for initial zero state,
            - a theano tensor variable (``ndim > 0``) containing initial state
              data, or
            - a dictionary containing a full output specifier. See
              ``outputs_info`` in the Theano documentation for ``scan``.
        name : str, optional
            Name of the scan variable to create. Defaults to ``'scan'``.
        step : callable, optional
            The callable to apply in the loop. Defaults to :func:`self._step`.
        constants : sequence of tensor, optional
            A sequence of parameters, if any, needed by the step function.

        Returns
        -------
        output(s) : theano expression(s)
            Theano expression(s) representing output(s) from the scan.
        updates : sequence of update tuples
            A sequence of updates to apply inside a theano function.
        '''
        init = []
        for i, x in enumerate(outputs):
            ndim = getattr(x, 'ndim', -1)
            if x is None or isinstance(x, dict) or ndim > 0:
                init.append(x)
                continue
            if isinstance(x, int) or ndim == 0:
                init.append(TT.repeat(theano.shared(
                    np.zeros((1, self.output_size), util.FLOAT),
                    name=self._fmt('init{}'.format(i))), x, axis=0))
                continue
            raise ValueError('cannot handle input {} for scan!'.format(x))
        return theano.scan(
            step or self._step,
            name=self._fmt(name),
            sequences=inputs,
            outputs_info=init,
            non_sequences=constants,
            go_backwards='back' in self.kwargs.get('direction', '').lower(),
            truncate_gradient=self.kwargs.get('bptt_limit', -1),
        )

Response: This method is used to define a basic loop in theano.


Instruction:
Create a Python 3 function for
creating a rate parameter for a recurrent layer.

Response:
def _create_rates(self, dist='uniform', size=None, eps=1e-4):
        '''Create a rate parameter (usually for a recurrent network layer).

        Parameters
        ----------
        dist : {'uniform', 'log'}, optional
            Distribution of rate values. Defaults to ``'uniform'``.
        size : int, optional
            Number of rates to create. Defaults to ``self.output_size``.
        eps : float, optional
            A "buffer" preventing rate values from getting too close to 0 or 1.
            Defaults to 1e-4.

        Returns
        -------
        rates : theano shared or None
            A vector of rate parameters for certain types of recurrent layers.
        '''
        if size is None:
            size = self.output_size
        if dist == 'uniform':
            z = np.random.uniform(eps, 1 - eps, size=size).astype(util.FLOAT)
            return theano.shared(z, name=self._fmt('rate'))
        if dist == 'log':
            z = np.random.uniform(-6, -eps, size=size).astype(util.FLOAT)
            return theano.shared(np.exp(z), name=self._fmt('rate'))
        return None


Instruction:
Write a Python 3 script for
constructing an activation function by name.

Response:
def build(name, layer, **kwargs):
    '''Construct an activation function by name.

    Parameters
    ----------
    name : str or :class:`Activation`
        The name of the type of activation function to build, or an
        already-created instance of an activation function.
    layer : :class:`theanets.layers.Layer`
        The layer to which this activation will be applied.
    kwargs : dict
        Additional named arguments to pass to the activation constructor.

    Returns
    -------
    activation : :class:`Activation`
        A neural network activation function instance.
    '''
    if isinstance(name, Activation):
        return name

    if '+' in name:
        return functools.reduce(
            Compose, (build(n, layer, **kwargs) for n in name.split('+')))

    act = COMMON.get(name)
    if act is not None:
        act.name = name
        act.params = []
        return act

    if name.lower().startswith('maxout') and ':' in name:
        name, pieces = name.split(':', 1)
        kwargs['pieces'] = int(pieces)
    kwargs['name'] = name
    kwargs['layer'] = layer
    return Activation.build(name, **kwargs)


Instruction:
Create a Python 3 function for
training a model using a training and validation set.

Response:
def itertrain(self, train, valid=None, **kwargs):
        '''Train a model using a training and validation set.

        This method yields a series of monitor values to the caller. After every
        iteration, a pair of monitor dictionaries is generated: one evaluated on
        the training dataset, and another evaluated on the validation dataset.
        The validation monitors might not be updated during every training
        iteration; in this case, the most recent validation monitors will be
        yielded along with the training monitors.

        Parameters
        ----------
        train : :class:`Dataset <theanets.dataset.Dataset>`
            A set of training data for computing updates to model parameters.
        valid : :class:`Dataset <theanets.dataset.Dataset>`
            A set of validation data for computing monitor values and
            determining when the loss has stopped improving.

        Yields
        ------
        training : dict
            A dictionary mapping monitor names to values, evaluated on the
            training dataset.
        validation : dict
            A dictionary containing monitor values evaluated on the validation
            dataset.
        '''
        for monitors in downhill.build(
                algo=self.algo,
                loss=self.network.loss(**kwargs),
                updates=self.network.updates(**kwargs),
                monitors=self.network.monitors(**kwargs),
                inputs=self.network.variables,
                params=self.network.params,
                monitor_gradients=kwargs.get('monitor_gradients', False),
        ).iterate(train, valid=valid, **kwargs):
            yield monitors


Instruction:
Can you generate the documentation for the following Python 3 function
def reservoir(xs, n, rng):
        '''Select a random sample of n items from xs.'''
        pool = []
        for i, x in enumerate(xs):
            if len(pool) < n:
                pool.append(x / np.linalg.norm(x))
                continue
            j = rng.randint(i + 1)
            if j < n:
                pool[j] = x / np.linalg.norm(x)
        # if the pool still has fewer than n items, pad with distorted random
        # duplicates from the source data.
        L = len(pool)
        S = np.std(pool, axis=0)
        while len(pool) < n:
            x = pool[rng.randint(L)]
            pool.append(x + S * rng.randn(*x.shape))
        return np.array(pool, dtype=pool[0].dtype)

Response: Select a random sample of n items from xs.


Instruction:
Write a Python 3 function that can
train a model using a training and validation set.

Response:
def itertrain(self, train, valid=None, **kwargs):
        '''Train a model using a training and validation set.

        This method yields a series of monitor values to the caller. After every
        iteration, a pair of monitor dictionaries is generated: one evaluated on
        the training dataset, and another evaluated on the validation dataset.
        The validation monitors might not be updated during every training
        iteration; in this case, the most recent validation monitors will be
        yielded along with the training monitors.

        Parameters
        ----------
        train : :class:`Dataset <theanets.dataset.Dataset>`
            A set of training data for computing updates to model parameters.
        valid : :class:`Dataset <theanets.dataset.Dataset>`
            A set of validation data for computing monitor values and
            determining when the loss has stopped improving.

        Yields
        ------
        training : dict
            A dictionary mapping monitor names to values, evaluated on the
            training dataset.
        validation : dict
            A dictionary containing monitor values evaluated on the validation
            dataset.
        '''
        ifci = itertools.chain.from_iterable

        def first(x):
            return x[0] if isinstance(x, (tuple, list)) else x

        def last(x):
            return x[-1] if isinstance(x, (tuple, list)) else x

        odim = idim = None
        for t in train:
            idim = first(t).shape[-1]
            odim = last(t).shape[-1]

        rng = kwargs.get('rng')
        if rng is None or isinstance(rng, int):
            rng = np.random.RandomState(rng)

        # set output (decoding) weights on the network.
        samples = ifci(last(t) for t in train)
        for param in self.network.layers[-1].params:
            shape = param.get_value(borrow=True).shape
            if len(shape) == 2 and shape[1] == odim:
                arr = np.vstack(SampleTrainer.reservoir(samples, shape[0], rng))
                util.log('setting {}: {}', param.name, shape)
                param.set_value(arr / np.sqrt((arr * arr).sum(axis=1))[:, None])

        # set input (encoding) weights on the network.
        samples = ifci(first(t) for t in train)
        for layer in self.network.layers:
            for param in layer.params:
                shape = param.get_value(borrow=True).shape
                if len(shape) == 2 and shape[0] == idim:
                    arr = np.vstack(SampleTrainer.reservoir(samples, shape[1], rng)).T
                    util.log('setting {}: {}', param.name, shape)
                    param.set_value(arr / np.sqrt((arr * arr).sum(axis=0)))
                    samples = ifci(self.network.feed_forward(
                        first(t))[i-1] for t in train)

        yield dict(loss=0), dict(loss=0)


Instruction:
Create a Python 3 function for
training a model using a training and validation set.

Response:
def itertrain(self, train, valid=None, **kwargs):
        '''Train a model using a training and validation set.

        This method yields a series of monitor values to the caller. After every
        iteration, a pair of monitor dictionaries is generated: one evaluated on
        the training dataset, and another evaluated on the validation dataset.
        The validation monitors might not be updated during every training
        iteration; in this case, the most recent validation monitors will be
        yielded along with the training monitors.

        Parameters
        ----------
        train : :class:`Dataset <theanets.dataset.Dataset>`
            A set of training data for computing updates to model parameters.
        valid : :class:`Dataset <theanets.dataset.Dataset>`
            A set of validation data for computing monitor values and
            determining when the loss has stopped improving.

        Yields
        ------
        training : dict
            A dictionary mapping monitor names to values, evaluated on the
            training dataset.
        validation : dict
            A dictionary containing monitor values evaluated on the validation
            dataset.
        '''
        net = self.network
        original = list(net.layers)
        output_name = original[-1].output_name
        tied = any(isinstance(l, layers.Tied) for l in original)
        L = 1 + len(original) // 2 if tied else len(original) - 1
        for i in range(1, L):
            tail = []
            if i == L - 1:
                net.layers = original
            elif tied:
                net.layers = original[:i+1]
                for j in range(i):
                    prev = tail[-1] if tail else net.layers[-1]
                    tail.append(layers.Layer.build(
                        'tied', partner=original[i-j].name, inputs=prev.name))
                net.layers = original[:i+1] + tail
            else:
                tail.append(layers.Layer.build(
                    'feedforward',
                    name='lwout',
                    inputs=original[i].output_name,
                    size=original[-1].output_size,
                    activation=original[-1].kwargs['activation']))
                net.layers = original[:i+1] + tail
            util.log('layerwise: training {}',
                     ' -> '.join(l.name for l in net.layers))
            [l.bind(net, initialize=False) for l in net.layers]
            [l.setup() for l in tail]
            net.losses[0].output_name = net.layers[-1].output_name
            trainer = DownhillTrainer(self.algo, net)
            for monitors in trainer.itertrain(train, valid, **kwargs):
                yield monitors
        net.layers = original
        net.losses[0].output_name = output_name


Instruction:
Write a Python 3 function that can
train a model using a training and validation set.

Response:
def itertrain(self, train, valid=None, **kwargs):
        '''Train a model using a training and validation set.

        This method yields a series of monitor values to the caller. After every
        iteration, a pair of monitor dictionaries is generated: one evaluated on
        the training dataset, and another evaluated on the validation dataset.
        The validation monitors might not be updated during every training
        iteration; in this case, the most recent validation monitors will be
        yielded along with the training monitors.

        Parameters
        ----------
        train : :class:`Dataset <theanets.dataset.Dataset>`
            A set of training data for computing updates to model parameters.
        valid : :class:`Dataset <theanets.dataset.Dataset>`
            A set of validation data for computing monitor values and
            determining when the loss has stopped improving.

        Yields
        ------
        training : dict
            A dictionary mapping monitor names to values, evaluated on the
            training dataset.
        validation : dict
            A dictionary containing monitor values evaluated on the validation
            dataset.
        '''
        from . import feedforward

        original_layer_names = set(l.name for l in self.network.layers[:-1])

        # construct a "shadow" of the input network, using the original
        # network's encoding layers, with tied weights in an autoencoder
        # configuration.
        layers_ = list(l.to_spec() for l in self.network.layers[:-1])
        for i, l in enumerate(layers_[::-1][:-2]):
            layers_.append(dict(
                form='tied', partner=l['name'], activation=l['activation']))
        layers_.append(dict(
            form='tied', partner=layers_[1]['name'], activation='linear'))

        util.log('creating shadow network')
        ae = feedforward.Autoencoder(layers=layers_)

        # train the autoencoder using the supervised layerwise pretrainer.
        pre = SupervisedPretrainer(self.algo, ae)
        for monitors in pre.itertrain(train, valid, **kwargs):
            yield monitors

        # copy trained parameter values back to our original network.
        for param in ae.params:
            l, p = param.name.split('.')
            if l in original_layer_names:
                util.log('copying pretrained parameter {}', param.name)
                self.network.find(l, p).set_value(param.get_value())

        util.log('completed unsupervised pretraining')


Instruction:
Can you generate a brief explanation for the following Python 3 code
def add_layer(self, layer=None, **kwargs):
        '''Add a :ref:`layer <layers>` to our network graph.

        Parameters
        ----------
        layer : int, tuple, dict, or :class:`Layer <theanets.layers.base.Layer>`
            A value specifying the layer to add. For more information, please
            see :ref:`guide-creating-specifying-layers`.
        '''
        # if the given layer is a Layer instance, just add it and move on.
        if isinstance(layer, layers.Layer):
            self.layers.append(layer)
            return

        form = kwargs.pop('form', 'ff' if self.layers else 'input').lower()

        if isinstance(layer, util.basestring):
            if not layers.Layer.is_registered(layer):
                raise util.ConfigurationError('unknown layer type: {}'.format(layer))
            form = layer
            layer = None

        # if layer is a tuple/list of integers, assume it's a shape.
        if isinstance(layer, (tuple, list)) and all(isinstance(x, int) for x in layer):
            kwargs['shape'] = tuple(layer)
            layer = None

        # if layer is some other tuple/list, assume it's a list of:
        # - the name of a layers.Layer class (str)
        # - the name of an activation function (str)
        # - the number of units in the layer (int)
        if isinstance(layer, (tuple, list)):
            for el in layer:
                if isinstance(el, util.basestring) and layers.Layer.is_registered(el):
                    form = el
                elif isinstance(el, util.basestring):
                    kwargs['activation'] = el
                elif isinstance(el, int):
                    if 'size' in kwargs:
                        raise util.ConfigurationError(
                            'duplicate layer sizes! {}'.format(kwargs))
                    kwargs['size'] = el
            layer = None

        # if layer is a dictionary, try to extract a form for the layer, and
        # override our default keyword arguments with the rest.
        if isinstance(layer, dict):
            for key, value in layer.items():
                if key == 'form':
                    form = value.lower()
                else:
                    kwargs[key] = value
            layer = None

        # if neither shape nor size have been specified yet, check that the
        # "layer" param is an int and use it for "size".
        if 'shape' not in kwargs and 'size' not in kwargs and isinstance(layer, int):
            kwargs['size'] = layer

        # if it hasn't been provided in some other way yet, set input
        # dimensionality based on the model.
        if form == 'input' and 'shape' not in kwargs:
            kwargs.setdefault('ndim', self.INPUT_NDIM)

        # set some default layer parameters.
        if form != 'input':
            kwargs.setdefault('inputs', self.layers[-1].output_name)
            kwargs.setdefault('rng', self._rng)

        if form.lower() == 'tied' and 'partner' not in kwargs:
            # we look backward through our list of layers for a partner.
            # any "tied" layer that we find increases a counter by one,
            # and any "untied" layer decreases the counter by one. our
            # partner is the first layer we find with count zero.
            #
            # this is intended to handle the hopefully common case of a
            # (possibly deep) tied-weights autoencoder.
            tied = 1
            partner = None
            for l in self.layers[::-1]:
                tied += 1 if isinstance(l, layers.Tied) else -1
                if tied == 0:
                    partner = l.name
                    break
            else:
                raise util.ConfigurationError(
                    'cannot find partner for "{}"'.format(kwargs))
            kwargs['partner'] = partner

        layer = layers.Layer.build(form, **kwargs)

        # check that graph inputs have unique names.
        if isinstance(layer, layers.Input):
            if any(layer.name == i.name for i in self.inputs):
                raise util.ConfigurationError(
                    '"{}": duplicate input name!'.format(layer.name))

        self.layers.append(layer)

Response: Adds a layer to the internal network.


Instruction:
Here you have a function in Python 3, explain what it does
def add_loss(self, loss=None, **kwargs):
        '''Add a :ref:`loss function <losses>` to the model.

        Parameters
        ----------
        loss : str, dict, or :class:`theanets.losses.Loss`
            A loss function to add. If this is a Loss instance, it will be added
            immediately. If this is a string, it names a loss function to build
            and add. If it is a dictionary, it should contain a ``'form'`` key
            whose string value names the loss function to add. Other arguments
            will be passed to :func:`theanets.losses.Loss.build`.
        '''
        if isinstance(loss, losses.Loss):
            self.losses.append(loss)
            return

        form = loss or 'mse'
        if 'form' in kwargs:
            form = kwargs.pop('form').lower()

        kw = dict(target=self.INPUT_NDIM, output_name=self.layers[-1].output_name)
        kw.update(kwargs)

        if isinstance(loss, dict):
            loss = dict(loss)
            if 'form' in loss:
                form = loss.pop('form').lower()
            kw.update(loss)

        self.losses.append(losses.Loss.build(form, **kw))

Response: Adds a loss function to the model.


Instruction:
Explain what the following Python 3 code does
def set_loss(self, *args, **kwargs):
        '''Clear the current loss functions from the network and add a new one.

        All parameters and keyword arguments are passed to :func:`add_loss`
        after clearing the current losses.
        '''
        self.losses = []
        self.add_loss(*args, **kwargs)

Response: Clear the current loss functions from the network and add a new one.


Instruction:
Write a Python 3 script to
train our network one batch at a time.

Response:
def itertrain(self, train, valid=None, algo='rmsprop', subalgo='rmsprop',
                  save_every=0, save_progress=None, **kwargs):
        '''Train our network, one batch at a time.

        This method yields a series of ``(train, valid)`` monitor pairs. The
        ``train`` value is a dictionary mapping names to monitor values
        evaluated on the training dataset. The ``valid`` value is also a
        dictionary mapping names to values, but these values are evaluated on
        the validation dataset.

        Because validation might not occur every training iteration, the
        validation monitors might be repeated for multiple training iterations.
        It is probably most helpful to think of the validation monitors as being
        the "most recent" values that have been computed.

        After training completes, the network attribute of this class will
        contain the trained network parameters.

        Parameters
        ----------
        train : :class:`Dataset <downhill.dataset.Dataset>` or list
            A dataset to use when training the network. If this is a
            ``downhill.Dataset`` instance, it will be used directly as the
            training datset. If it is a list of numpy arrays or a list of
            callables, it will be converted to a ``downhill.Dataset`` and then
            used as the training set.
        valid : :class:`Dataset <downhill.dataset.Dataset>` or list, optional
            If this is provided, it will be used as a validation dataset. If not
            provided, the training set will be used for validation. (This is not
            recommended!)
        algo : str, optional
            An optimization algorithm to use for training our network. If not
            provided, :class:`RMSProp <downhill.adaptive.RMSProp>` will be used.
        subalgo : str, optional
            An optimization algorithm to use for a trainer that requires a
            "sub-algorithm," sugh as an unsupervised pretrainer. Defaults to
            :class:`RMSProp <downhill.adaptive.RMSProp>`.
        save_every : int or float, optional
            If this is nonzero and ``save_progress`` is not None, then the model
            being trained will be saved periodically. If this is a float, it is
            treated as a number of minutes to wait between savings. If it is an
            int, it is treated as the number of training epochs to wait between
            savings. Defaults to 0.
        save_progress : str or file handle, optional
            If this is not None, and ``save_progress`` is nonzero, then save the
            model periodically during training. This parameter gives either (a)
            the full path of a file to save the model, or (b) a file-like object
            where the model should be saved. If it is a string and the given
            name contains a "{}" format specifier, it will be filled with the
            integer Unix timestamp at the time the model is saved. Defaults to
            None, which does not save models.

        Yields
        ------
        training : dict
            A dictionary of monitor values computed using the training dataset,
            at the conclusion of training. This dictionary will at least contain
            a 'loss' key that indicates the value of the loss function. Other
            keys may be available depending on the trainer being used.
        validation : dict
            A dictionary of monitor values computed using the validation
            dataset, at the conclusion of training.
        '''
        if 'rng' not in kwargs:
            kwargs['rng'] = self._rng

        def create_dataset(data, **kwargs):
            name = kwargs.get('name', 'dataset')
            s = '{}_batches'.format(name)
            return downhill.Dataset(
                data,
                name=name,
                batch_size=kwargs.get('batch_size', 32),
                iteration_size=kwargs.get('iteration_size', kwargs.get(s)),
                axis=kwargs.get('axis', 0),
                rng=kwargs['rng'])

        # set up datasets ...
        if valid is None:
            valid = train
        if not isinstance(valid, downhill.Dataset):
            valid = create_dataset(valid, name='valid', **kwargs)
        if not isinstance(train, downhill.Dataset):
            train = create_dataset(train, name='train', **kwargs)

        if 'algorithm' in kwargs:
            warnings.warn(
                'please use the "algo" keyword arg instead of "algorithm"',
                DeprecationWarning)
            algo = kwargs.pop('algorithm')
            if isinstance(algo, (list, tuple)):
                algo = algo[0]

        # set up trainer ...
        if isinstance(algo, util.basestring):
            algo = algo.lower()
            if algo == 'sample':
                algo = trainer.SampleTrainer(self)
            elif algo.startswith('layer') or algo.startswith('sup'):
                algo = trainer.SupervisedPretrainer(subalgo, self)
            elif algo.startswith('pre') or algo.startswith('unsup'):
                algo = trainer.UnsupervisedPretrainer(subalgo, self)
            else:
                algo = trainer.DownhillTrainer(algo, self)

        # set up check to save model ...
        def needs_saving(elapsed, iteration):
            if save_progress is None:
                return False
            if isinstance(save_every, float):
                return elapsed > 60 * save_every
            if isinstance(save_every, int):
                return iteration % save_every == 0
            return False

        # train it!
        start = time.time()
        for i, monitors in enumerate(algo.itertrain(train, valid, **kwargs)):
            yield monitors
            now = time.time()
            if i and needs_saving(now - start, i):
                filename_or_handle = save_progress
                if isinstance(filename_or_handle, util.basestring):
                    filename_or_handle = save_progress.format(int(now))
                self.save(filename_or_handle)
                start = now


Instruction:
How would you explain what the following Python 3 function does
def train(self, *args, **kwargs):
        '''Train the network until the trainer converges.

        All arguments are passed to :func:`itertrain`.

        Returns
        -------
        training : dict
            A dictionary of monitor values computed using the training dataset,
            at the conclusion of training. This dictionary will at least contain
            a 'loss' key that indicates the value of the loss function. Other
            keys may be available depending on the trainer being used.
        validation : dict
            A dictionary of monitor values computed using the validation
            dataset, at the conclusion of training.
        '''
        monitors = None
        for monitors in self.itertrain(*args, **kwargs):
            pass
        return monitors

Response: Train the network until the trainer converges.


Instruction:
Explain what the following Python 3 code does
def _hash(self, regularizers=()):
        '''Construct a string key for representing a computation graph.

        This key will be unique for a given (a) network topology, (b) set of
        losses, and (c) set of regularizers.

        Returns
        -------
        key : str
            A hash representing the computation graph for the current network.
        '''
        def add(s):
            h.update(str(s).encode('utf-8'))
        h = hashlib.md5()
        for l in self.layers:
            add('{}{}{}'.format(l.__class__.__name__, l.name, l.output_shape))
        for l in self.losses:
            add('{}{}'.format(l.__class__.__name__, l.weight))
        for r in regularizers:
            add('{}{}{}'.format(r.__class__.__name__, r.weight, r.pattern))
        return h.hexdigest()

Response: Construct a string key for representing a computation graph.


Instruction:
Write a Python 3 script for
connecting the layers in this network to form a computation graph.

Response:
def build_graph(self, regularizers=()):
        '''Connect the layers in this network to form a computation graph.

        Parameters
        ----------
        regularizers : list of :class:`theanets.regularizers.Regularizer`
            A list of the regularizers to apply while building the computation
            graph.

        Returns
        -------
        outputs : list of Theano variables
            A list of expressions giving the output of each layer in the graph.
        updates : list of update tuples
            A list of updates that should be performed by a Theano function that
            computes something using this graph.
        '''
        key = self._hash(regularizers)
        if key not in self._graphs:
            util.log('building computation graph')
            for loss in self.losses:
                loss.log()
            for reg in regularizers:
                reg.log()
            outputs = {}
            updates = []
            for layer in self.layers:
                out, upd = layer.connect(outputs)
                for reg in regularizers:
                    reg.modify_graph(out)
                outputs.update(out)
                updates.extend(upd)
            self._graphs[key] = outputs, updates
        return self._graphs[key]


Instruction:
Make a summary of the following Python 3 code
def inputs(self):
        '''A list of Theano variables for feedforward computations.'''
        return [l.input for l in self.layers if isinstance(l, layers.Input)]

Response: A list of Theano variables for feedforward computations.


Instruction:
Make a summary of the following Python 3 code
def find(self, which, param):
        '''Get a parameter from a layer in the network.

        Parameters
        ----------
        which : int or str
            The layer that owns the parameter to return.

            If this is an integer, then 0 refers to the input layer, 1 refers
            to the first hidden layer, 2 to the second, and so on.

            If this is a string, the layer with the corresponding name, if any,
            will be used.

        param : int or str
            Name of the parameter to retrieve from the specified layer, or its
            index in the parameter list of the layer.

        Raises
        ------
        KeyError
            If there is no such layer, or if there is no such parameter in the
            specified layer.

        Returns
        -------
        param : Theano shared variable
            A shared parameter variable from the indicated layer.
        '''
        for i, layer in enumerate(self.layers):
            if which == i or which == layer.name:
                return layer.find(param)
        raise KeyError(which)

Response: Find a parameter from a layer in the network.


Instruction:
Can you generate the documentation for the following Python 3 function
def feed_forward(self, x, **kwargs):
        '''Compute a forward pass of all layers from the given input.

        All keyword arguments are passed directly to :func:`build_graph`.

        Parameters
        ----------
        x : ndarray (num-examples, num-variables)
            An array containing data to be fed into the network. Multiple
            examples are arranged as rows in this array, with columns containing
            the variables for each example.

        Returns
        -------
        layers : list of ndarray (num-examples, num-units)
            The activation values of each layer in the the network when given
            input `x`. For each of the hidden layers, an array is returned
            containing one row per input example; the columns of each array
            correspond to units in the respective layer. The "output" of the
            network is the last element of this list.
        '''
        regs = regularizers.from_kwargs(self, **kwargs)
        key = self._hash(regs)
        if key not in self._functions:
            outputs, updates = self.build_graph(regs)
            labels, exprs = list(outputs.keys()), list(outputs.values())
            util.log('compiling feed_forward function')
            self._functions[key] = (labels, theano.function(
                self.inputs, exprs, updates=updates))
        labels, f = self._functions[key]
        return dict(zip(labels, f(x)))

Response: Compute a forward pass of all layers from the given input.


Instruction:
Make a summary of the following Python 3 code
def predict(self, x, **kwargs):
        '''Compute a forward pass of the inputs, returning the network output.

        All keyword arguments end up being passed to :func:`build_graph`.

        Parameters
        ----------
        x : ndarray (num-examples, num-variables)
            An array containing data to be fed into the network. Multiple
            examples are arranged as rows in this array, with columns containing
            the variables for each example.

        Returns
        -------
        y : ndarray (num-examples, num-variables)
            Returns the values of the network output units when given input `x`.
            Rows in this array correspond to examples, and columns to output
            variables.
        '''
        return self.feed_forward(x, **kwargs)[self.layers[-1].output_name]

Response: Compute a forward pass of the inputs returning the network output.


Instruction:
Make a summary of the following Python 3 code
def score(self, x, y, w=None, **kwargs):
        '''Compute R^2 coefficient of determination for a given labeled input.

        Parameters
        ----------
        x : ndarray (num-examples, num-inputs)
            An array containing data to be fed into the network. Multiple
            examples are arranged as rows in this array, with columns containing
            the variables for each example.
        y : ndarray (num-examples, num-outputs)
            An array containing expected target data for the network. Multiple
            examples are arranged as rows in this array, with columns containing
            the variables for each example.

        Returns
        -------
        r2 : float
            The R^2 correlation between the prediction of this netork and its
            target output.
        '''
        u = y - self.predict(x, **kwargs)
        v = y - y.mean()
        if w is None:
            w = np.ones_like(u)
        return 1 - (w * u * u).sum() / (w * v * v).sum()

Response: Compute R^2 coefficient of determination of determination for a given labeled input.


Instruction:
Write a Python 3 script to
save the state of this network to a pickle file on disk.

Response:
def save(self, filename_or_handle):
        '''Save the state of this network to a pickle file on disk.

        Parameters
        ----------
        filename_or_handle : str or file handle
            Save the state of this network to a pickle file. If this parameter
            is a string, it names the file where the pickle will be saved. If it
            is a file-like object, this object will be used for writing the
            pickle. If the filename ends in ".gz" then the output will
            automatically be gzipped.
        '''
        if isinstance(filename_or_handle, util.basestring):
            opener = gzip.open if filename_or_handle.lower().endswith('.gz') else open
            handle = opener(filename_or_handle, 'wb')
        else:
            handle = filename_or_handle
        pickle.dump(self, handle, -1)
        if isinstance(filename_or_handle, util.basestring):
            handle.close()
        util.log('saved model to {}', filename_or_handle)


Instruction:
Create a Python 3 function for
loading a saved network from disk.

Response:
def load(cls, filename_or_handle):
        '''Load a saved network from disk.

        Parameters
        ----------
        filename_or_handle : str or file handle
            Load the state of this network from a pickle file. If this parameter
            is a string, it names the file where the pickle will be saved. If it
            is a file-like object, this object will be used for reading the
            pickle. If the filename ends in ".gz" then the output will
            automatically be gunzipped.
        '''
        assert not isinstance(cls, Network), \
            'cannot load an instance! say instead: net = Network.load(source)'
        if isinstance(filename_or_handle, util.basestring):
            opener = gzip.open if filename_or_handle.lower().endswith('.gz') else open
            handle = opener(filename_or_handle, 'rb')
        else:
            handle = filename_or_handle
        model = pickle.load(handle)
        if isinstance(filename_or_handle, util.basestring):
            handle.close()
        util.log('loaded model from {}', filename_or_handle)
        return model


Instruction:
Can you implement a function in Python 3 that
returns a variable representing the regularized loss for this network.

Response:
def loss(self, **kwargs):
        '''Return a variable representing the regularized loss for this network.

        The regularized loss includes both the :ref:`loss computation <losses>`
        for the network as well as any :ref:`regularizers <regularizers>` that
        are in place.

        Keyword arguments are passed directly to
        :func:`theanets.regularizers.from_kwargs`.

        Returns
        -------
        loss : Theano expression
            A Theano expression representing the loss of this network.
        '''
        regs = regularizers.from_kwargs(self, **kwargs)
        outputs, _ = self.build_graph(regs)
        return sum(l.weight * l(outputs) for l in self.losses) + \
            sum(r.weight * r.loss(self.layers, outputs) for r in regs)


Instruction:
Write a Python 3 function that can
return expressions that should be computed to monitor training.

Response:
def monitors(self, **kwargs):
        '''Return expressions that should be computed to monitor training.

        Returns
        -------
        monitors : list of (name, expression) pairs
            A list of named monitor expressions to compute for this network.
        '''
        regs = regularizers.from_kwargs(self, **kwargs)
        outputs, _ = self.build_graph(regs)
        monitors = [('err', self.losses[0](outputs))]

        def matching(pattern):
            '''Yield all matching outputs or parameters from the graph.'''
            for name, expr in util.outputs_matching(outputs, pattern):
                yield name, expr
            for name, expr in util.params_matching(self.layers, pattern):
                yield name, expr

        def parse_levels(levels):
            '''Yield named monitor callables.'''
            if isinstance(levels, dict):
                levels = levels.items()
            if isinstance(levels, (int, float)):
                levels = [levels]
            for level in levels:
                if isinstance(level, (tuple, list)):
                    label, call = level
                    yield ':{}'.format(label), call
                if isinstance(level, (int, float)):
                    def call(expr):
                        return (expr < level).mean()
                    yield '<{}'.format(level), call

        inputs = kwargs.get('monitors', {})
        if isinstance(inputs, dict):
            inputs = inputs.items()
        for pattern, levels in inputs:
            for name, expr in matching(pattern):
                for key, value in parse_levels(levels):
                    monitors.append(('{}{}'.format(name, key), value(expr)))

        return monitors


Instruction:
Can you generate the documentation for the following Python 3 function
def updates(self, **kwargs):
        '''Return expressions to run as updates during network training.

        Returns
        -------
        updates : list of (parameter, expression) pairs
            A list of named parameter update expressions for this network.
        '''
        regs = regularizers.from_kwargs(self, **kwargs)
        _, updates = self.build_graph(regs)
        return updates

Response: Return expressions to run as updates during training.


Instruction:
Can you write a function in Python 3 where it
names of layer with one input.

Response:
def input_name(self):
        '''Name of layer input (for layers with one input).'''
        if len(self._input_shapes) != 1:
            raise util.ConfigurationError(
                'expected one input for layer "{}", got {}'
                .format(self.name, self._input_shapes))
        return list(self._input_shapes)[0]


Instruction:
Can you write a function in Python 3 where it
sizes of layer input.

Response:
def input_size(self):
        '''Size of layer input (for layers with one input).'''
        shape = self.input_shape
        if shape is None:
            raise util.ConfigurationError(
                'undefined input size for layer "{}"'.format(self.name))
        return shape[-1]


Instruction:
How would you explain what the following Python 3 function does
def output_size(self):
        '''Number of "neurons" in this layer's default output.'''
        shape = self.output_shape
        if shape is None:
            raise util.ConfigurationError(
                'undefined output size for layer "{}"'.format(self.name))
        return shape[-1]

Response: Number of neurons in this layer s default output.


Instruction:
Can you create a Python 3 function that
creates Theano variables representing the outputs of this layer.

Response:
def connect(self, inputs):
        '''Create Theano variables representing the outputs of this layer.

        Parameters
        ----------
        inputs : dict of Theano expressions
            Symbolic inputs to this layer, given as a dictionary mapping string
            names to Theano expressions. Each string key should be of the form
            "{layer_name}:{output_name}" and refers to a specific output from
            a specific layer in the graph.

        Returns
        -------
        outputs : dict
            A dictionary mapping names to Theano expressions for the outputs
            from this layer.
        updates : sequence of (parameter, expression) tuples
            Updates that should be performed by a Theano function that computes
            something using this layer.
        '''
        outputs, updates = self.transform(inputs)
        # transform the outputs to be a list of ordered pairs if needed.
        if isinstance(outputs, dict):
            outputs = sorted(outputs.items())
        if isinstance(outputs, (TT.TensorVariable, SS.SparseVariable)):
            outputs = [('out', outputs)]
        outs = {self.full_name(name): expr for name, expr in outputs}
        return outs, updates


Instruction:
Can you implement a function in Python 3 that
binds this layer into a computation graph.

Response:
def bind(self, graph, reset=True, initialize=True):
        '''Bind this layer into a computation graph.

        This method is a wrapper for performing common initialization tasks. It
        calls :func:`resolve`, :func:`setup`, and :func:`log`.

        Parameters
        ----------
        graph : :class:`Network <theanets.graph.Network>`
            A computation network in which this layer is to be bound.
        reset : bool, optional
            If ``True`` (the default), reset the resolved layers for this layer.
        initialize : bool, optional
            If ``True`` (the default), initialize the parameters for this layer
            by calling :func:`setup`.

        Raises
        ------
        theanets.util.ConfigurationError :
            If an input cannot be resolved.
        '''
        if reset:
            for k in self._input_shapes:
                self._input_shapes[k] = None
            for k in self._output_shapes:
                self._output_shapes[k] = None
        self.resolve_inputs(graph.layers)
        self.resolve_outputs()
        self.activate = activations.build(
            self.kwargs.get('activation', 'relu'), self)
        if initialize:
            self.setup()
        self.log()


Instruction:
Here you have a function in Python 3, explain what it does
def resolve_inputs(self, layers):
        '''Resolve the names of inputs for this layer into shape tuples.

        Parameters
        ----------
        layers : list of :class:`Layer`
            A list of the layers that are available for resolving inputs.

        Raises
        ------
        theanets.util.ConfigurationError :
            If an input cannot be resolved.
        '''
        resolved = {}
        for name, shape in self._input_shapes.items():
            if shape is None:
                name, shape = self._resolve_shape(name, layers)
            resolved[name] = shape
        self._input_shapes = resolved

Response: Resolve the names of inputs for this layer into shape tuples.


Instruction:
Make a summary of the following Python 3 code
def resolve_outputs(self):
        '''Resolve the names of outputs for this layer into shape tuples.'''
        input_shape = None
        for i, shape in enumerate(self._input_shapes.values()):
            if i == 0:
                input_shape = shape
            if len(input_shape) != len(shape) or any(
                    a is not None and b is not None and a != b
                    for a, b in zip(input_shape[:-1], shape[:-1])):
                raise util.ConfigurationError(
                    'layer "{}" incompatible input shapes {}'
                    .format(self.name, self._input_shapes))
        size = self.kwargs.get('size')
        shape = self.kwargs.get('shape')
        if shape is not None:
            pass
        elif size is not None:
            shape = tuple(input_shape[:-1]) + (size, )
        else:
            raise util.ConfigurationError(
                'layer "{}" does not specify a size'.format(self.name))
        self._output_shapes['out'] = shape

Response: Resolve the names of outputs for this layer into shape tuples.


Instruction:
Explain what the following Python 3 code does
def log(self):
        '''Log some information about this layer.'''
        inputs = ', '.join('"{0}" {1}'.format(*ns) for ns in self._input_shapes.items())
        util.log('layer {0.__class__.__name__} "{0.name}" {0.output_shape} {1} from {2}',
                 self, getattr(self.activate, 'name', self.activate), inputs)
        util.log('learnable parameters: {}', self.log_params())

Response: Log some information about this layer.


Instruction:
Given the following Python 3 function, write the documentation
def log_params(self):
        '''Log information about this layer's parameters.'''
        total = 0
        for p in self.params:
            shape = p.get_value().shape
            util.log('parameter "{}" {}', p.name, shape)
            total += np.prod(shape)
        return total

Response: Log information about this layer s parameters.


Instruction:
Can you tell what is the following Python 3 function doing
def _resolve_shape(self, name, layers):
        '''Given a list of layers, find the layer output with the given name.

        Parameters
        ----------
        name : str
            Name of a layer to resolve.
        layers : list of :class:`theanets.layers.base.Layer`
            A list of layers to search in.

        Raises
        ------
        util.ConfigurationError :
            If there is no such layer, or if there are more than one.

        Returns
        -------
        name : str
            The fully-scoped name of the desired output.
        shape : tuple of None and/or int
            The shape of the named output.
        '''
        matches = [l for l in layers if name.split(':')[0] == l.name]
        if len(matches) != 1:
            raise util.ConfigurationError(
                'layer "{}" cannot resolve "{}" using {}'
                .format(self.name, name, [l.name for l in layers]))
        name = name if ':' in name else matches[0].output_name
        return name, matches[0]._output_shapes[name.split(':')[1]]

Response: Given a list of layers find the layer output with the given name.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def find(self, key):
        '''Get a shared variable for a parameter by name.

        Parameters
        ----------
        key : str or int
            The name of the parameter to look up, or the index of the parameter
            in our parameter list. These are both dependent on the
            implementation of the layer.

        Returns
        -------
        param : shared variable
            A shared variable containing values for the given parameter.

        Raises
        ------
        KeyError
            If a param with the given name does not exist.
        '''
        name = self._fmt(str(key))
        for i, p in enumerate(self._params):
            if key == i or name == p.name:
                return p
        raise KeyError(key)

Response: Get a shared variable for a parameter by name.


Instruction:
Given the following Python 3 function, write the documentation
def add_weights(self, name, nin, nout, mean=0, std=0, sparsity=0, diagonal=0):
        '''Helper method to create a new weight matrix.

        Parameters
        ----------
        name : str
            Name of the parameter to add.
        nin : int
            Size of "input" for this weight matrix.
        nout : int
            Size of "output" for this weight matrix.
        mean : float, optional
            Mean value for randomly-initialized weights. Defaults to 0.
        std : float, optional
            Standard deviation of initial matrix values. Defaults to
            :math:`1 / sqrt(n_i + n_o)`.
        sparsity : float, optional
            Fraction of weights to be set to zero. Defaults to 0.
        diagonal : float, optional
            Initialize weights to a matrix of zeros with this value along the
            diagonal. Defaults to None, which initializes all weights randomly.
        '''
        glorot = 1 / np.sqrt(nin + nout)
        m = self.kwargs.get(
            'mean_{}'.format(name), self.kwargs.get('mean', mean))
        s = self.kwargs.get(
            'std_{}'.format(name), self.kwargs.get('std', std or glorot))
        p = self.kwargs.get(
            'sparsity_{}'.format(name), self.kwargs.get('sparsity', sparsity))
        d = self.kwargs.get(
            'diagonal_{}'.format(name), self.kwargs.get('diagonal', diagonal))
        self._params.append(theano.shared(
            util.random_matrix(nin, nout, mean=m, std=s, sparsity=p,
                               diagonal=d, rng=self.rng),
            name=self._fmt(name)))

Response: Helper method to create a new weight matrix.


Instruction:
How would you implement a function in Python 3 that
creates a specification dictionary for this layer.

Response:
def to_spec(self):
        '''Create a specification dictionary for this layer.

        Returns
        -------
        spec : dict
            A dictionary specifying the configuration of this layer.
        '''
        spec = dict(**self.kwargs)
        spec.update(
            form=self.__class__.__name__.lower(),
            name=self.name,
            activation=self.kwargs.get('activation', 'relu'),
        )
        return spec


Instruction:
How would you implement a function in Python 3 that
returns the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax from C by returning the ArgMax

Response:
def argmax(self, C):
        """
        Returns the ArgMax from C by returning the
        (x_pos, y_pos, theta, scale)  tuple

        >>> C = np.random.randn(10, 10, 5, 4)
        >>> x_pos, y_pos, theta, scale = mp.argmax(C)
        >>> C[x_pos][y_pos][theta][scale] = C.max()

        """
        ind = np.absolute(C).argmax()
        return np.unravel_index(ind, C.shape)


Instruction:
Here you have a function in Python 3, explain what it does
def band(self, sf_0, B_sf, force=False):
        if sf_0 == 0.:
            return 1.
        elif self.pe.use_cache and not force:
            tag = str(sf_0) + '_' + str(B_sf)
            try:
                return self.cache['band'][tag]
            except:
                if self.pe.verbose>50: print('doing band cache for tag ', tag)
                self.cache['band'][tag] = self.band(sf_0, B_sf, force=True)
                return self.cache['band'][tag]
        else:
            # see http://en.wikipedia.org/wiki/Log-normal_distribution
            env = 1./self.f*np.exp(-.5*(np.log(self.f/sf_0)**2)/B_sf**2)
        return env

Response: Returns the radial frequency envelope of a given preferred spatial frequency and bandwidth.


Instruction:
Can you implement a function in Python 3 that
returns the orientation of the object in the specified time - domain.

Response:
def orientation(self, theta, B_theta, force=False):
        """
        Returns the orientation envelope:
        We use a von-Mises distribution on the orientation:
        - mean orientation is ``theta`` (in radians),
        - ``B_theta`` is the bandwidth (in radians). It is equal to the standard deviation of the Gaussian
        envelope which approximate the distribution for low bandwidths. The Half-Width at Half Height is
        given by approximately np.sqrt(2*B_theta_**2*np.log(2)).

        # selecting one direction,  theta is the mean direction, B_theta the spread
        # we use a von-mises distribution on the orientation
        # see http://en.wikipedia.org/wiki/Von_Mises_distribution
        """
        if B_theta is np.inf: # for large bandwidth, returns a strictly flat envelope
            enveloppe_orientation = 1.
        elif self.pe.use_cache and not force:
            tag = str(theta) + '_' + str(B_theta)
            try:
                return self.cache['orientation'][tag]
            except:
                if self.pe.verbose>50: print('doing orientation cache for tag ', tag)
                self.cache['orientation'][tag] = self.orientation(theta, B_theta, force=True)
                return self.cache['orientation'][tag]
        else: # non pathological case
            # As shown in:
            #  http://www.csse.uwa.edu.au/~pk/research/matlabfns/PhaseCongruency/Docs/convexpl.html
            # this single bump allows (without the symmetric) to code both symmetric
            # and anti-symmetric parts in one shot.
            cos_angle = np.cos(self.f_theta-theta)
            enveloppe_orientation = np.exp(cos_angle/B_theta**2)
        return enveloppe_orientation


Instruction:
Explain what the following Python 3 code does
def loggabor(self, x_pos, y_pos, sf_0, B_sf, theta, B_theta, preprocess=True):

        env = np.multiply(self.band(sf_0, B_sf), self.orientation(theta, B_theta))
        if not(x_pos==0.) and not(y_pos==0.): # bypass translation whenever none is needed
              env = env.astype(np.complex128) * self.trans(x_pos*1., y_pos*1.)
        if preprocess : env *= self.f_mask # retina processing
        # normalizing energy:
        env /= np.sqrt((np.abs(env)**2).mean())
        # in the case a a single bump (see ``orientation``), we should compensate the fact that the distribution gets complex:
        env *= np.sqrt(2.)
        return env

Response: Returns the envelope of a loggabor with the given parameters


Instruction:
Write a Python 3 script to
return the image of a LogGabor with the given parameters

Response:
def loggabor_image(self, x_pos, y_pos, theta, sf_0, phase, B_sf, B_theta):
        """
        Returns the image of a LogGabor

        Note that the convention for coordinates follows that of matrices:
        the origin is at the top left of the image, and coordinates are first
        the rows (vertical axis, going down) then the columns (horizontal axis,
        going right).

        """

        FT_lg = self.loggabor(x_pos, y_pos, sf_0=sf_0, B_sf=B_sf, theta=theta, B_theta=B_theta)
        FT_lg = FT_lg * np.exp(1j * phase)
        return self.invert(FT_lg, full=False)


Instruction:
Explain what the following Python 3 code does
def from_file(self, ifile, codec='ascii'):
        if ifile.read(12) == b'ooBinaryFile':
            def bin2str(ifile):
                textlen = struct.unpack('>h', ifile.read(2))[0]
                # Single byte characters
                if textlen >= 0:
                    return ifile.read(textlen).decode('ascii')
                # Multi byte characters have initial len -1 and then \xff bytes
                elif textlen == -1:
                    textlen = struct.unpack('>h', ifile.read(2))[0]
                    data = ifile.read(textlen*2)
                    # Hack to go from number to unicode in python3 and python2
                    fun = unichr if 'unichr' in __builtins__ else chr
                    charlist = (data[i:i+2] for i in range(0, len(data), 2))
                    return u''.join(
                        fun(struct.unpack('>h', i)[0]) for i in charlist)

            ifile.read(ord(ifile.read(1)))  # skip oo type
            self.xmin = struct.unpack('>d', ifile.read(8))[0]
            self.xmax = struct.unpack('>d', ifile.read(8))[0]
            ifile.read(1)  # skip <exists>
            self.tier_num = struct.unpack('>i', ifile.read(4))[0]
            for i in range(self.tier_num):
                tier_type = ifile.read(ord(ifile.read(1))).decode('ascii')
                name = bin2str(ifile)
                tier = Tier(0, 0, name=name, tier_type=tier_type)
                self.tiers.append(tier)
                tier.xmin = struct.unpack('>d', ifile.read(8))[0]
                tier.xmax = struct.unpack('>d', ifile.read(8))[0]
                nint = struct.unpack('>i', ifile.read(4))[0]
                for i in range(nint):
                    x1 = struct.unpack('>d', ifile.read(8))[0]
                    if tier.tier_type == 'IntervalTier':
                        x2 = struct.unpack('>d', ifile.read(8))[0]
                    text = bin2str(ifile)
                    if tier.tier_type == 'IntervalTier':
                        tier.intervals.append((x1, x2, text))
                    elif tier.tier_type == 'TextTier':
                        tier.intervals.append((x1, text))
                    else:
                        raise Exception('Tiertype does not exist.')
        else:
            def nn(ifile, pat):
                line = next(ifile).decode(codec)
                return pat.search(line).group(1)

            regfloat = re.compile('([\d.]+)\s*$', flags=re.UNICODE)
            regint = re.compile('([\d]+)\s*$', flags=re.UNICODE)
            regstr = re.compile('"(.*)"\s*$', flags=re.UNICODE)
            # Skip the Headers and empty line
            next(ifile), next(ifile), next(ifile)
            self.xmin = float(nn(ifile, regfloat))
            self.xmax = float(nn(ifile, regfloat))
            # Skip <exists>
            line = next(ifile)
            short = line.strip() == b'<exists>'
            self.tier_num = int(nn(ifile, regint))
            not short and next(ifile)
            for i in range(self.tier_num):
                not short and next(ifile)  # skip item[]: and item[\d]:
                tier_type = nn(ifile, regstr)
                name = nn(ifile, regstr)
                tier = Tier(0, 0, name=name, tier_type=tier_type)
                self.tiers.append(tier)
                tier.xmin = float(nn(ifile, regfloat))
                tier.xmax = float(nn(ifile, regfloat))
                for i in range(int(nn(ifile, regint))):
                    not short and next(ifile)  # skip intervals [\d]
                    x1 = float(nn(ifile, regfloat))
                    if tier.tier_type == 'IntervalTier':
                        x2 = float(nn(ifile, regfloat))
                        t = nn(ifile, regstr)
                        tier.intervals.append((x1, x2, t))
                    elif tier.tier_type == 'TextTier':
                        t = nn(ifile, regstr)
                        tier.intervals.append((x1, t))

Response: Read a single or multi - byte text grid from a file.


Instruction:
Can you generate the documentation for the following Python 3 function
def sort_tiers(self, key=lambda x: x.name):
        self.tiers.sort(key=key)

Response: Sort the tiers given the key function.


Instruction:
Create a Python 3 function to
add an interval or text tier to the specified location.

Response:
def add_tier(self, name, tier_type='IntervalTier', number=None):
        """Add an IntervalTier or a TextTier on the specified location.

        :param str name: Name of the tier, duplicate names is allowed.
        :param str tier_type: Type of the tier.
        :param int number: Place to insert the tier, when ``None`` the number
            is generated and the tier will be placed on the bottom.
        :returns: The created tier.
        :raises ValueError: If the number is out of bounds.
        """
        if number is None:
            number = 1 if not self.tiers else len(self.tiers)+1
        elif number < 1 or number > len(self.tiers):
            raise ValueError('Number not in [1..{}]'.format(len(self.tiers)))
        elif tier_type not in Tier.P_TIERS:
            raise ValueError('tier_type has to be in {}'.format(self.P_TIERS))
        self.tiers.insert(number-1,
                          Tier(self.xmin, self.xmax, name, tier_type))
        return self.tiers[number-1]


Instruction:
How would you code a function in Python 3 to
remove a tier from the cache.

Response:
def remove_tier(self, name_num):
        """Remove a tier, when multiple tiers exist with that name only the
        first is removed.

        :param name_num: Name or number of the tier to remove.
        :type name_num: int or str
        :raises IndexError: If there is no tier with that number.
        """
        if isinstance(name_num, int):
            del(self.tiers[name_num-1])
        else:
            self.tiers = [i for i in self.tiers if i.name != name_num]


Instruction:
How would you code a function in Python 3 to
give a tier when multiple tiers exist with that name only the first one is returned.

Response:
def get_tier(self, name_num):
        """Gives a tier, when multiple tiers exist with that name only the
        first is returned.

        :param name_num: Name or number of the tier to return.
        :type name_num: int or str
        :returns: The tier.
        :raises IndexError: If the tier doesn't exist.
        """
        return self.tiers[name_num - 1] if isinstance(name_num, int) else\
            [i for i in self.tiers if i.name == name_num][0]


Instruction:
Write a Python 3 function that can
write the object to a file.

Response:
def to_file(self, filepath, codec='utf-8', mode='normal'):
        """Write the object to a file.

        :param str filepath: Path of the fil.
        :param str codec: Text encoding.
        :param string mode: Flag to for write mode, possible modes:
            'n'/'normal', 's'/'short' and 'b'/'binary'
        """
        self.tier_num = len(self.tiers)
        if mode in ['binary', 'b']:
            with open(filepath, 'wb') as f:
                def writebstr(s):
                    try:
                        bstr = s.encode('ascii')
                    except UnicodeError:
                        f.write(b'\xff\xff')
                        bstr = b''.join(struct.pack('>h', ord(c)) for c in s)
                    f.write(struct.pack('>h', len(s)))
                    f.write(bstr)

                f.write(b'ooBinaryFile\x08TextGrid')
                f.write(struct.pack('>d', self.xmin))
                f.write(struct.pack('>d', self.xmax))
                f.write(b'\x01')
                f.write(struct.pack('>i', self.tier_num))
                for tier in self.tiers:
                    f.write(chr(len(tier.tier_type)).encode('ascii'))
                    f.write(tier.tier_type.encode('ascii'))
                    writebstr(tier.name)
                    f.write(struct.pack('>d', tier.xmin))
                    f.write(struct.pack('>d', tier.xmax))
                    ints = tier.get_all_intervals()
                    f.write(struct.pack('>i', len(ints)))
                    itier = tier.tier_type == 'IntervalTier'
                    for c in ints:
                        f.write(struct.pack('>d', c[0]))
                        itier and f.write(struct.pack('>d', c[1]))
                        writebstr(c[2 if itier else 1])
        elif mode in ['normal', 'n', 'short', 's']:
            with codecs.open(filepath, 'w', codec) as f:
                short = mode[0] == 's'

                def wrt(indent, prefix, value, ff=''):
                    indent = 0 if short else indent
                    prefix = '' if short else prefix
                    if value is not None or not short:
                        s = u'{{}}{{}}{}\n'.format(ff)
                        f.write(s.format(' '*indent, prefix, value))

                f.write(u'File type = "ooTextFile"\n'
                        u'Object class = "TextGrid"\n\n')
                wrt(0, u'xmin = ', self.xmin, '{:f}')
                wrt(0, u'xmax = ', self.xmax, '{:f}')
                wrt(0, u'tiers? ', u'<exists>', '{}')
                wrt(0, u'size = ', self.tier_num, '{:d}')
                wrt(0, u'item []:', None)
                for tnum, tier in enumerate(self.tiers, 1):
                    wrt(4, u'item [{:d}]:'.format(tnum), None)
                    wrt(8, u'class = ', tier.tier_type, '"{}"')
                    wrt(8, u'name = ', tier.name, '"{}"')
                    wrt(8, u'xmin = ', tier.xmin, '{:f}')
                    wrt(8, u'xmax = ', tier.xmax, '{:f}')
                    if tier.tier_type == 'IntervalTier':
                        ints = tier.get_all_intervals()
                        wrt(8, u'intervals: size = ', len(ints), '{:d}')
                        for i, c in enumerate(ints):
                            wrt(8, 'intervals [{:d}]:'.format(i+1), None)
                            wrt(12, 'xmin = ', c[0], '{:f}')
                            wrt(12, 'xmax = ', c[1], '{:f}')
                            wrt(12, 'text = ', c[2].replace('"', '""'), '"{}"')
                    elif tier.tier_type == 'TextTier':
                        wrt(8, u'points: size = ', len(tier.intervals), '{:d}')
                        for i, c in enumerate(tier.get_intervals()):
                            wrt(8, 'points [{:d}]:'.format(i+1), None)
                            wrt(12, 'number = ', c[0], '{:f}')
                            wrt(12, 'mark = ', c[1].replace('"', '""'), '"{}"')
        else:
            raise Exception('Unknown mode')


Instruction:
Can you create a Python 3 function that
converts the object to an Eaf object.

Response:
def to_eaf(self, skipempty=True, pointlength=0.1):
        """Convert the object to an pympi.Elan.Eaf object

        :param int pointlength: Length of respective interval from points in
                                seconds
        :param bool skipempty: Skip the empty annotations
        :returns: :class:`pympi.Elan.Eaf` object
        :raises ImportError: If the Eaf module can't be loaded.
        :raises ValueError: If the pointlength is not strictly positive.
        """
        from pympi.Elan import Eaf
        eaf_out = Eaf()
        if pointlength <= 0:
            raise ValueError('Pointlength should be strictly positive')
        for tier in self.get_tiers():
            eaf_out.add_tier(tier.name)
            for ann in tier.get_intervals(True):
                if tier.tier_type == 'TextTier':
                    ann = (ann[0], ann[0]+pointlength, ann[1])
                if ann[2].strip() or not skipempty:
                    eaf_out.add_annotation(tier.name, int(round(ann[0]*1000)),
                                           int(round(ann[1]*1000)), ann[2])
        return eaf_out


Instruction:
Write a Python 3 script for
adding a point to the TextTier.

Response:
def add_point(self, point, value, check=True):
        """Add a point to the TextTier

        :param int point: Time of the point.
        :param str value: Text of the point.
        :param bool check: Flag to check for overlap.
        :raises Exception: If overlap or wrong tiertype.
        """
        if self.tier_type != 'TextTier':
            raise Exception('Tiertype must be TextTier.')
        if check and any(i for i in self.intervals if i[0] == point):
                raise Exception('No overlap is allowed')
        self.intervals.append((point, value))


Instruction:
Create a Python 3 function for
adding an interval to the IntervalTier.

Response:
def add_interval(self, begin, end, value, check=True):
        """Add an interval to the IntervalTier.

        :param float begin: Start time of the interval.
        :param float end: End time of the interval.
        :param str value: Text of the interval.
        :param bool check: Flag to check for overlap.
        :raises Exception: If overlap, begin > end or wrong tiertype.
        """
        if self.tier_type != 'IntervalTier':
            raise Exception('Tiertype must be IntervalTier')
        if check:
            if any(i for i in self.intervals if begin < i[1] and end > i[0]):
                raise Exception('No overlap is allowed')
            if begin > end:
                raise Exception('Begin must be smaller then end')
        self.intervals.append((begin, end, value))


Instruction:
Can you write a function in Python 3 where it
removes an interval from the list of intervals.

Response:
def remove_interval(self, time):
        """Remove an interval, if no interval is found nothing happens.

        :param int time: Time of the interval.
        :raises TierTypeException: If the tier is not a IntervalTier.
        """
        if self.tier_type != 'IntervalTier':
            raise Exception('Tiertype must be IntervalTier.')
        self.intervals = [i for i in self.intervals
                          if not(i[0] <= time and i[1] >= time)]


Instruction:
Write a Python 3 script to
remove a point from the set of points.

Response:
def remove_point(self, time):
        """Remove a point, if no point is found nothing happens.

        :param int time: Time of the point.
        :raises TierTypeException: If the tier is not a TextTier.
        """
        if self.tier_type != 'TextTier':
            raise Exception('Tiertype must be TextTier.')
        self.intervals = [i for i in self.intervals if i[0] != time]


Instruction:
Implement a Python 3 function for
giving all the intervals or points sorted.

Response:
def get_intervals(self, sort=False):
        """Give all the intervals or points.

        :param bool sort: Flag for yielding the intervals or points sorted.
        :yields: All the intervals
        """
        for i in sorted(self.intervals) if sort else self.intervals:
            yield i


Instruction:
Can you create a Python 3 function that
returns the true list of intervals including the empty intervals.

Response:
def get_all_intervals(self):
        """Returns the true list of intervals including the empty intervals."""
        ints = sorted(self.get_intervals(True))
        if self.tier_type == 'IntervalTier':
            if not ints:
                ints.append((self.xmin, self.xmax, ''))
            else:
                if ints[0][0] > self.xmin:
                    ints.insert(0, (self.xmin, ints[0][0], ''))
                if ints[-1][1] < self.xmax:
                    ints.append((ints[-1][1], self.xmax, ''))
                p = ints[-1]
                for index, i in reversed(list(enumerate(ints[:-1], 1))):
                    if p[0] - i[1] != 0:
                        ints.insert(index, (i[1], p[0], ''))
                    p = i
        return ints


Instruction:
Write a Python 3 function for
reading a. cha file and converts it to an ELAN object.

Response:
def eaf_from_chat(file_path, codec='ascii', extension='wav'):
    """Reads a .cha file and converts it to an elan object. The functions tries
    to mimic the CHAT2ELAN program that comes with the CLAN package as close as
    possible. This function however converts to the latest ELAN file format
    since the library is designed for it. All CHAT headers will be added as
    Properties in the object and the headers that have a similar field in an
    Eaf file will be added there too. The file description of chat files can be
    found `here <http://childes.psy.cmu.edu/manuals/CHAT.pdf>`_.

    :param str file_path: The file path of the .cha file.
    :param str codec: The codec, if the @UTF8 header is present it will choose
        utf-8, default is ascii. Older CHAT files don't have their encoding
        embedded in a header so you will probably need to choose some obscure
        ISO charset then.
    :param str extension: The extension of the media file.
    :throws StopIteration: If the file doesn't contain a @End header, thus
        inferring the file is broken.
    """
    eafob = Eaf()
    eafob.add_linguistic_type('parent')
    eafob.add_linguistic_type(
        'child', constraints='Symbolic_Association', timealignable=False)
    participantsdb = {}
    last_annotation = None
    with open(file_path, 'r') as chatin:
        while True:
            line = chatin.readline().strip().decode(codec)
            if line == '@UTF8':  # Codec marker
                codec = 'utf8'
                continue
            elif line == '@End':  # End of file marker
                break
            elif line.startswith('@') and line != '@Begin':  # Header marker
                key, value = line.split(':\t')
                eafob.add_property('{}:\t'.format(key), value)
                if key == '@Languages':
                    for language in value.split(','):
                        eafob.add_language(language)
                elif key == '@Participants':
                    for participant in value.split(','):
                        splits = participant.strip().split(' ')
                        splits = map(lambda x: x.replace('_', ' '), splits)
                        if len(splits) == 2:
                            participantsdb[splits[0]] = (None, splits[1])
                        elif len(splits) == 3:
                            participantsdb[splits[0]] = (splits[1], splits[2])
                elif key == '@ID':
                    ids = map(lambda x: x.replace('_', ''), value.split('|'))
                    eafob.add_tier(ids[2], part=participantsdb[ids[2]][0],
                                   language=ids[0])
                elif key == '@Media':
                    media = value.split(',')
                    eafob.add_linked_file(
                        'file://{}.{}'.format(media[0], extension))
                elif key == '@Transcriber:':
                    for tier in eafob.get_tier_names():
                        eafob.tiers[tier][2]['ANNOTATOR'] = value
            elif line.startswith('*'):  # Main tier marker
                while len(line.split('\x15')) != 3:
                    line += chatin.readline().decode(codec).strip()
                for participant in participantsdb.keys():
                    if line.startswith('*{}:'.format(participant)):
                        splits = ''.join(line.split(':')[1:]).strip()
                        utt, time, _ = splits.split('\x15')
                        time = map(int, time.split('_'))
                        last_annotation = (participant, time[0], time[1], utt)
                        eafob.add_annotation(*last_annotation)
            elif line.startswith('%'):  # Dependant tier marker
                splits = line.split(':')
                name = '{}_{}'.format(last_annotation[0], splits[0][1:])
                if name not in eafob.get_tier_names():
                    eafob.add_tier(name, 'child', last_annotation[0])
                eafob.add_ref_annotation(
                    name, last_annotation[0], sum(last_annotation[1:3])/2,
                    ''.join(splits[1:]).strip())
    return eafob


Instruction:
Implement a Python 3 function for
parsing an EAF file and return a new EAF object.

Response:
def parse_eaf(file_path, eaf_obj):
    """Parse an EAF file

    :param str file_path: Path to read from, - for stdin.
    :param pympi.Elan.Eaf eaf_obj: Existing EAF object to put the data in.
    :returns: EAF object.
    """
    if file_path == '-':
        file_path = sys.stdin
    # Annotation document
    try:
        tree_root = etree.parse(file_path).getroot()
    except etree.ParseError:
        raise Exception('Unable to parse eaf, can you open it in ELAN?')

    if tree_root.attrib['VERSION'] not in ['2.8', '2.7']:
        sys.stdout.write('Parsing unknown version of ELAN spec... '
                         'This could result in errors...\n')
    eaf_obj.adocument.update(tree_root.attrib)
    del(eaf_obj.adocument['{http://www.w3.org/2001/XMLSchema-instance}noNamesp'
                          'aceSchemaLocation'])
    tier_number = 0
    for elem in tree_root:
        # Licence
        if elem.tag == 'LICENSE':
            eaf_obj.licenses.append((elem.text, elem.attrib['LICENSE_URL']))
        # Header
        if elem.tag == 'HEADER':
            eaf_obj.header.update(elem.attrib)
            for elem1 in elem:
                if elem1.tag == 'MEDIA_DESCRIPTOR':
                    eaf_obj.media_descriptors.append(elem1.attrib)
                elif elem1.tag == 'LINKED_FILE_DESCRIPTOR':
                    eaf_obj.linked_file_descriptors.append(elem1.attrib)
                elif elem1.tag == 'PROPERTY':
                    eaf_obj.properties.append(
                        (elem1.attrib['NAME'], elem1.text))
        # Time order
        elif elem.tag == 'TIME_ORDER':
            for elem1 in elem:
                tsid = elem1.attrib['TIME_SLOT_ID']
                tsnum = int(''.join(filter(str.isdigit, tsid)))
                if tsnum and tsnum > eaf_obj.maxts:
                    eaf_obj.maxts = tsnum
                ts = elem1.attrib.get('TIME_VALUE', None)
                eaf_obj.timeslots[tsid] = ts if ts is None else int(ts)
        # Tier
        elif elem.tag == 'TIER':
            tier_id = elem.attrib['TIER_ID']
            align = {}
            ref = {}
            for elem1 in elem:
                if elem1.tag == 'ANNOTATION':
                    for elem2 in elem1:
                        if elem2.tag == 'ALIGNABLE_ANNOTATION':
                            annot_id = elem2.attrib['ANNOTATION_ID']
                            annot_num = int(''.join(
                                filter(str.isdigit, annot_id)))
                            if annot_num and annot_num > eaf_obj.maxaid:
                                eaf_obj.maxaid = annot_num
                            annot_start = elem2.attrib['TIME_SLOT_REF1']
                            annot_end = elem2.attrib['TIME_SLOT_REF2']
                            svg_ref = elem2.attrib.get('SVG_REF', None)
                            align[annot_id] = (annot_start, annot_end,
                                               '' if not list(elem2)[0].text
                                               else list(elem2)[0].text,
                                               svg_ref)
                            eaf_obj.annotations[annot_id] = tier_id
                        elif elem2.tag == 'REF_ANNOTATION':
                            annot_ref = elem2.attrib['ANNOTATION_REF']
                            previous = elem2.attrib.get('PREVIOUS_ANNOTATION',
                                                        None)
                            annot_id = elem2.attrib['ANNOTATION_ID']
                            annot_num = int(''.join(
                                filter(str.isdigit, annot_id)))
                            if annot_num and annot_num > eaf_obj.maxaid:
                                eaf_obj.maxaid = annot_num
                            svg_ref = elem2.attrib.get('SVG_REF', None)
                            ref[annot_id] = (annot_ref,
                                             '' if not list(elem2)[0].text else
                                             list(elem2)[0].text,
                                             previous, svg_ref)
                            eaf_obj.annotations[annot_id] = tier_id
            eaf_obj.tiers[tier_id] = (align, ref, elem.attrib, tier_number)
            tier_number += 1
        # Linguistic type
        elif elem.tag == 'LINGUISTIC_TYPE':
            eaf_obj.linguistic_types[elem.attrib['LINGUISTIC_TYPE_ID']] =\
                elem.attrib
        # Locale
        elif elem.tag == 'LOCALE':
            eaf_obj.locales[elem.attrib['LANGUAGE_CODE']] =\
                (elem.attrib.get('COUNTRY_CODE', None),
                 elem.attrib.get('VARIANT', None))
        # Language
        elif elem.tag == 'LANGUAGE':
            eaf_obj.languages[elem.attrib['LANG_ID']] =\
                (elem.attrib.get('LANG_DEF', None),
                 elem.attrib.get('LANG_LABEL', None))
        # Constraint
        elif elem.tag == 'CONSTRAINT':
            eaf_obj.constraints[elem.attrib['STEREOTYPE']] =\
                elem.attrib['DESCRIPTION']
        # Controlled vocabulary
        elif elem.tag == 'CONTROLLED_VOCABULARY':
            cv_id = elem.attrib['CV_ID']
            ext_ref = elem.attrib.get('EXT_REF', None)
            descriptions = []

            if 'DESCRIPTION' in elem.attrib:
                eaf_obj.languages['und'] = (
                    'http://cdb.iso.org/lg/CDB-00130975-001',
                    'undetermined (und)')
                descriptions.append(('und', elem.attrib['DESCRIPTION']))
            entries = {}
            for elem1 in elem:
                if elem1.tag == 'DESCRIPTION':
                    descriptions.append((elem1.attrib['LANG_REF'], elem1.text))
                elif elem1.tag == 'CV_ENTRY':
                    cve_value = (elem1.text, 'und',
                                 elem1.get('DESCRIPTION', None))
                    entries['cveid{}'.format(len(entries))] = \
                        ([cve_value], elem1.attrib.get('EXT_REF', None))
                elif elem1.tag == 'CV_ENTRY_ML':
                    cem_ext_ref = elem1.attrib.get('EXT_REF', None)
                    cve_id = elem1.attrib['CVE_ID']
                    cve_values = []
                    for elem2 in elem1:
                        if elem2.tag == 'CVE_VALUE':
                            cve_values.append((elem2.text,
                                               elem2.attrib['LANG_REF'],
                                               elem2.get('DESCRIPTION', None)))
                    entries[cve_id] = (cve_values, cem_ext_ref)
            eaf_obj.controlled_vocabularies[cv_id] =\
                (descriptions, entries, ext_ref)
        # Lexicon ref
        elif elem.tag == 'LEXICON_REF':
            eaf_obj.lexicon_refs[elem.attrib['LEX_REF_ID']] = elem.attrib
        # External ref
        elif elem.tag == 'EXTERNAL_REF':
            eaf_obj.external_refs[elem.attrib['EXT_REF_ID']] = (
                elem.attrib['TYPE'], elem.attrib['VALUE'])


Instruction:
Write a Python 3 script to
function to pretty print the xml.

Response:
def indent(el, level=0):
    """Function to pretty print the xml, meaning adding tabs and newlines.

    :param ElementTree.Element el: Current element.
    :param int level: Current level.
    """
    i = '\n' + level * '\t'
    if len(el):
        if not el.text or not el.text.strip():
            el.text = i+'\t'
        if not el.tail or not el.tail.strip():
            el.tail = i
        for elem in el:
            indent(elem, level+1)
        if not el.tail or not el.tail.strip():
            el.tail = i
    else:
        if level and (not el.tail or not el.tail.strip()):
            el.tail = i


Instruction:
Implement a Python 3 function for
writing an Eaf object to file.

Response:
def to_eaf(file_path, eaf_obj, pretty=True):
    """Write an Eaf object to file.

    :param str file_path: Filepath to write to, - for stdout.
    :param pympi.Elan.Eaf eaf_obj: Object to write.
    :param bool pretty: Flag to set pretty printing.
    """
    def rm_none(x):
        try:  # Ugly hack to test if s is a string in py3 and py2
            basestring

            def isstr(s):
                return isinstance(s, basestring)
        except NameError:
            def isstr(s):
                return isinstance(s, str)
        return {k: v if isstr(v) else str(v) for k, v in x.items()
                if v is not None}
    # Annotation Document
    ADOCUMENT = etree.Element('ANNOTATION_DOCUMENT', eaf_obj.adocument)
    # Licence
    for m in eaf_obj.licenses:
        n = etree.SubElement(ADOCUMENT, 'LICENSE', {'LICENSE_URL': m[1]})
        n.text = m[0]
    # Header
    HEADER = etree.SubElement(ADOCUMENT, 'HEADER', eaf_obj.header)
    # Media descriptiors
    for m in eaf_obj.media_descriptors:
        etree.SubElement(HEADER, 'MEDIA_DESCRIPTOR', rm_none(m))
    # Linked file descriptors
    for m in eaf_obj.linked_file_descriptors:
        etree.SubElement(HEADER, 'LINKED_FILE_DESCRIPTOR', rm_none(m))
    # Properties
    for k, v in eaf_obj.properties:
        etree.SubElement(HEADER, 'PROPERTY', {'NAME': k}).text = str(v)
    # Time order
    TIME_ORDER = etree.SubElement(ADOCUMENT, 'TIME_ORDER')
    for t in sorted(eaf_obj.timeslots.items(), key=lambda x: int(x[0][2:])):
        etree.SubElement(TIME_ORDER, 'TIME_SLOT', rm_none(
            {'TIME_SLOT_ID': t[0], 'TIME_VALUE': t[1]}))
    # Tiers
    for t in sorted(eaf_obj.tiers.items(), key=lambda x: x[1][3]):
        tier = etree.SubElement(ADOCUMENT, 'TIER', rm_none(t[1][2]))
        for a in t[1][0].items():
            ann = etree.SubElement(tier, 'ANNOTATION')
            alan = etree.SubElement(ann, 'ALIGNABLE_ANNOTATION', rm_none(
                {'ANNOTATION_ID': a[0], 'TIME_SLOT_REF1': a[1][0],
                 'TIME_SLOT_REF2': a[1][1], 'SVG_REF': a[1][3]}))
            etree.SubElement(alan, 'ANNOTATION_VALUE').text = a[1][2]
        for a in t[1][1].items():
            ann = etree.SubElement(tier, 'ANNOTATION')
            rean = etree.SubElement(ann, 'REF_ANNOTATION', rm_none(
                {'ANNOTATION_ID': a[0], 'ANNOTATION_REF': a[1][0],
                 'PREVIOUS_ANNOTATION': a[1][2], 'SVG_REF': a[1][3]}))
            etree.SubElement(rean, 'ANNOTATION_VALUE').text = a[1][1]
    # Linguistic types
    for l in eaf_obj.linguistic_types.values():
        etree.SubElement(ADOCUMENT, 'LINGUISTIC_TYPE', rm_none(l))
    # Locales
    for lc, (cc, vr) in eaf_obj.locales.items():
        etree.SubElement(ADOCUMENT, 'LOCALE', rm_none(
            {'LANGUAGE_CODE': lc, 'COUNTRY_CODE': cc, 'VARIANT': vr}))
    # Languages
    for lid, (ldef, label) in eaf_obj.languages.items():
        etree.SubElement(ADOCUMENT, 'LANGUAGE', rm_none(
            {'LANG_ID': lid, 'LANG_DEF': ldef, 'LANG_LABEL': label}))
    # Constraints
    for l in eaf_obj.constraints.items():
        etree.SubElement(ADOCUMENT, 'CONSTRAINT', rm_none(
            {'STEREOTYPE': l[0], 'DESCRIPTION': l[1]}))
    # Controlled vocabularies
    for cvid, (descriptions, cv_entries, ext_ref) in\
            eaf_obj.controlled_vocabularies.items():
        cv = etree.SubElement(ADOCUMENT, 'CONTROLLED_VOCABULARY',
                              rm_none({'CV_ID': cvid, 'EXT_REF': ext_ref}))
        for lang_ref, description in descriptions:
            des = etree.SubElement(cv, 'DESCRIPTION', {'LANG_REF': lang_ref})
            if description:
                des.text = description
        for cveid, (values, ext_ref) in cv_entries.items():
            cem = etree.SubElement(cv, 'CV_ENTRY_ML', rm_none({
                'CVE_ID': cveid, 'EXT_REF': ext_ref}))
            for value, lang_ref, description in values:
                val = etree.SubElement(cem, 'CVE_VALUE', rm_none({
                    'LANG_REF': lang_ref, 'DESCRIPTION': description}))
                val.text = value
    # Lexicon refs
    for l in eaf_obj.lexicon_refs.values():
        etree.SubElement(ADOCUMENT, 'LEXICON_REF', rm_none(l))
    # Exteral refs
    for eid, (etype, value) in eaf_obj.external_refs.items():
        etree.SubElement(ADOCUMENT, 'EXTERNAL_REF', rm_none(
            {'EXT_REF_ID': eid, 'TYPE': etype, 'VALUE': value}))

    if pretty:
        indent(ADOCUMENT)
    if file_path == '-':
        try:
            sys.stdout.write(etree.tostring(ADOCUMENT, encoding='unicode'))
        except LookupError:
            sys.stdout.write(etree.tostring(ADOCUMENT, encoding='UTF-8'))
    else:
        if os.access(file_path, os.F_OK):
            os.rename(file_path, '{}.bak'.format(file_path))
        etree.ElementTree(ADOCUMENT).write(
            file_path, xml_declaration=True, encoding='UTF-8')


Instruction:
Can you generate a brief explanation for the following Python 3 code
def add_annotation(self, id_tier, start, end, value='', svg_ref=None):
        if self.tiers[id_tier][1]:
            raise ValueError('Tier already contains ref annotations...')
        if start == end:
            raise ValueError('Annotation length is zero...')
        if start > end:
            raise ValueError('Annotation length is negative...')
        if start < 0:
            raise ValueError('Start is negative...')
        start_ts = self.generate_ts_id(start)
        end_ts = self.generate_ts_id(end)
        aid = self.generate_annotation_id()
        self.annotations[aid] = id_tier
        self.tiers[id_tier][0][aid] = (start_ts, end_ts, value, svg_ref)

Response: Adds an annotation to the metadata.