Source code for wiggelen.transform

"""
Various transformations on wiggle tracks.

.. moduleauthor:: Martijn Vermaat <martijn@vermaat.name>

.. Licensed under the MIT license, see the LICENSE file.
"""


from __future__ import division

from collections import deque


# Difference directions.
_BACKWARD, _FORWARD, _CENTRAL = 0, 1, 2


def _divided_difference(walker, direction=_CENTRAL, step=None,
                        auto_step=False):
    queue_size = 3 if direction == _CENTRAL else 2
    current = 0 if direction == _FORWARD else 1
    queue = deque(maxlen=queue_size)

    for region, position, value in walker:
        # Oldest entry is automatically dropped when exceeding maxlen.
        queue.append((region, position, value))
        regions, positions, values = zip(*queue)

        # Initialize step size.
        if step is None and auto_step and len(queue) > 1:
            step = positions[1] - positions[0]

        # Make sure derivative is defined for current position.
        if (len(queue) != queue_size or
            regions[-1] != regions[0] or
            (step and any(b - a != step
                          for a, b in zip(positions, positions[1:])))):
            continue

        yield (regions[current], positions[current],
               (values[-1] - values[0]) / (positions[-1] - positions[0]))


[docs]def forward_divided_difference(walker, step=None, auto_step=False): """ Derivative calculated by the forward divided difference method. .. note:: This transformation only works on walkers with numerical values. :arg walker: Generator yielding tuples of (region, position, value) per defined position. :type walker: generator(str, int, float) :arg step: Restrict calculation to positions that are this far apart (no restriction if `None`). :type step: int :arg auto_step: If `True` and `step=None`, automatically set `step` to a value based on the first two positions in `walker`. :type auto_step: bool :return: Tuple of (region, position, derivative value) per defined position in `walker` for which the derivative value is defined. :rtype: generator(str, int, float) """ return _divided_difference(walker, direction=_FORWARD, step=step, auto_step=auto_step)
[docs]def backward_divided_difference(walker, step=None, auto_step=False): """ Derivative calculated by the backward divided difference method. .. note:: This transformation only works on walkers with numerical values. :arg walker: Generator yielding tuples of (region, position, value) per defined position. :type walker: generator(str, int, float) :arg step: Restrict calculation to positions that are this far apart (no restriction if `None`). :type step: int :arg auto_step: If `True` and `step=None`, automatically set `step` to a value based on the first two positions in `walker`. :type auto_step: bool :return: Tuple of (region, position, derivative value) per defined position in `walker` for which the derivative value is defined. :rtype: generator(str, int, float) """ return _divided_difference(walker, direction=_BACKWARD, step=step, auto_step=auto_step)
[docs]def central_divided_difference(walker, step=None): """ Derivative calculated by the central divided difference method. .. note:: This transformation only works on walkers with numerical values. :arg walker: Generator yielding tuples of (region, position, value) per defined position. :type walker: generator(str, int, float) :arg step: Restrict calculation to positions that are this far apart. If `None`, automatically set `step` to a value based on the first two positions in `walker`. :type step: int :return: Tuple of (region, position, derivative value) per defined position in `walker` for which the derivative value is defined. :rtype: generator(str, int, float) """ return _divided_difference(walker, direction=_CENTRAL, step=step, auto_step=step is None)