Beispiel #1
0
def iterspace(features, sortem=False):
    """
    Returns a generator that yields each of the points defined by the
    discrete space 'features'.  The 'rightmost' feature is iterated
    most rapidly.  There is no requirement that the items in a feature
    be mutually unique.

    If optional 'sortem' is True, the items in each feature will be
    sorted before the space is enumerated.

    >>> features = (('b', 'a'), (1, 2, 1), ('p', 'n'))
    >>> tuple(iterspace(features))
    (('b', 1, 'p'), ('b', 1, 'n'), ('b', 2, 'p'), ('b', 2, 'n'), ('b', 1, 'p'), ('b', 1, 'n'), ('a', 1, 'p'), ('a', 1, 'n'), ('a', 2, 'p'), ('a', 2, 'n'), ('a', 1, 'p'), ('a', 1, 'n'))

    >>> tuple(iterspace(((3, 1, 2), ('z', 'a')), True))
    ((1, 'a'), (1, 'z'), (2, 'a'), (2, 'z'), (3, 'a'), (3, 'z'))
    """

    # sorted or as is; use frozentuple to verify immutability of feature values
    collect = sorted if sortem else tuple
    features = tuple(frozentuple(collect(feature)) for feature in features)

    ndim = len(features)

    # bootstrap the combinatoric work with the iterator's next for the first dimension
    iterstack = [iter(features[0]).next]
    valstack = [None]
    while True:
        try:
            # advance the last element; can raise StopIteration or IndexError
            valstack[-1] = iterstack[-1]()
            # fill out remaining dimensions of the iterators and the values
            while len(iterstack) < ndim:
                feature_iter = iter(features[len(iterstack)]).next
                iterstack.append(feature_iter)
                valstack.append(feature_iter())
            yield tuple(valstack)
        except StopIteration:
            # drop back so lower dimension gets advanced
            iterstack.pop()
            valstack.pop()
        except IndexError:
            return
Beispiel #2
0
def iterspace(features, sortem=False):
    """
    Returns a generator that yields each of the points defined by the
    discrete space 'features'.  The 'rightmost' feature is iterated
    most rapidly.  There is no requirement that the items in a feature
    be mutually unique.

    If optional 'sortem' is True, the items in each feature will be
    sorted before the space is enumerated.

    >>> features = (('b', 'a'), (1, 2, 1), ('p', 'n'))
    >>> tuple(iterspace(features))
    (('b', 1, 'p'), ('b', 1, 'n'), ('b', 2, 'p'), ('b', 2, 'n'), ('b', 1, 'p'), ('b', 1, 'n'), ('a', 1, 'p'), ('a', 1, 'n'), ('a', 2, 'p'), ('a', 2, 'n'), ('a', 1, 'p'), ('a', 1, 'n'))

    >>> tuple(iterspace(((3, 1, 2), ('z', 'a')), True))
    ((1, 'a'), (1, 'z'), (2, 'a'), (2, 'z'), (3, 'a'), (3, 'z'))
    """

    # sorted or as is; use frozentuple to verify immutability of feature values
    collect = sorted if sortem else tuple
    features = tuple(frozentuple(collect(feature)) for feature in features)

    ndim = len(features)

    # bootstrap the combinatoric work with the iterator's next for the first dimension
    iterstack = [iter(features[0]).next]
    valstack = [None]
    while True:
        try:
            # advance the last element; can raise StopIteration or IndexError
            valstack[-1] = iterstack[-1]()
            # fill out remaining dimensions of the iterators and the values
            while len(iterstack) < ndim:
                feature_iter = iter(features[len(iterstack)]).next
                iterstack.append(feature_iter)
                valstack.append(feature_iter())
            yield tuple(valstack)
        except StopIteration:
            # drop back so lower dimension gets advanced
            iterstack.pop()
            valstack.pop()
        except IndexError:
            return
Beispiel #3
0
    def __call__(self, length, shift, norm=None):
        key = length, shift, norm
        windows = self.windows
        hamming = windows.get(key)

        if hamming is None:

            # check preconditions etc
            if int(length) != length or length < 0:
                raise ValueError("expected non-negative integral length, got %s" % (length,))
            length = int(length)
            if int(shift) != shift or shift < 0:
                raise ValueError("expected non-negative integral shift, got %s" % (shift,))
            shift = int(shift)
            if not (norm is None or norm == 'sum' or norm == 'sumsq' or norm == 'mode'):
                raise ValueError("expected norm of None or 'sum' or 'mode', got %s" % (repr(norm),))
            key = frozentuple(key)

            if length == 0:
                hamming = frozentuple()
            elif length == 1:
                hamming = frozentuple([float(1 << shift)])
            else:
                # create unscaled Hamming window values

                bottom = self.BOTTOM
                cos_offset = self.COS_OFFSET
                cos_scale = self.COS_SCALE

                length1 = length - 1
                twopireciplength1 = 2 * PI / length1
                hamming = [None] * length

                left, right = 0, length1
                numbottom = 0
                while left <= right:
                    val = cos_offset - cos_scale * cos(twopireciplength1 * left)
                    assert bottom <= val <= 1
                    if val == bottom:
                        numbottom += 1
                    hamming[left] = hamming[right] = val
                    left += 1
                    right -= 1
                assert numbottom > 0
                assert (hamming[length1 // 2] == 1
                        or (length % 2 == 0 and hamming[(length1-1) // 2] == hamming[length1 // 2]))

                # scale and truncate

                # note: we truncate rather than round; for the
                # positive data in the window this errs on the side of
                # slightly less energy than if we rounded, but it avoids
                # the problem of rounding making the sum be more than
                # 1 for clients using the 'sum'-to-one normalization

                if norm is None:
                    norm_sum = 1
                elif norm == 'mode':
                    norm_sum = hamming[length1 // 2]
                    assert norm_sum == hamming[length // 2]
                elif norm == 'sum':
                    norm_sum = sum(hamming)
                elif norm == 'sumsq':
                    norm_sum = sqrt(sum(h*h for h in hamming))
                else:
                    assert False, "unreachable"

                assert norm_sum > 0
                norm_scale = float(1 << shift) / norm_sum
                hamming = windows[key] = frozentuple(int(h * norm_scale) for h in hamming)

        assert type(hamming) is frozentuple
        return hamming            
Beispiel #4
0
    def __call__(self, length, shift, norm=None):
        key = length, shift, norm
        windows = self.windows
        hamming = windows.get(key)

        if hamming is None:

            # check preconditions etc
            if int(length) != length or length < 0:
                raise ValueError(
                    "expected non-negative integral length, got %s" %
                    (length, ))
            length = int(length)
            if int(shift) != shift or shift < 0:
                raise ValueError(
                    "expected non-negative integral shift, got %s" % (shift, ))
            shift = int(shift)
            if not (norm is None or norm == 'sum' or norm == 'sumsq'
                    or norm == 'mode'):
                raise ValueError(
                    "expected norm of None or 'sum' or 'mode', got %s" %
                    (repr(norm), ))
            key = frozentuple(key)

            if length == 0:
                hamming = frozentuple()
            elif length == 1:
                hamming = frozentuple([float(1 << shift)])
            else:
                # create unscaled Hamming window values

                bottom = self.BOTTOM
                cos_offset = self.COS_OFFSET
                cos_scale = self.COS_SCALE

                length1 = length - 1
                twopireciplength1 = 2 * PI / length1
                hamming = [None] * length

                left, right = 0, length1
                numbottom = 0
                while left <= right:
                    val = cos_offset - cos_scale * cos(
                        twopireciplength1 * left)
                    assert bottom <= val <= 1
                    if val == bottom:
                        numbottom += 1
                    hamming[left] = hamming[right] = val
                    left += 1
                    right -= 1
                assert numbottom > 0
                assert (hamming[length1 // 2] == 1
                        or (length % 2 == 0 and hamming[(length1 - 1) // 2]
                            == hamming[length1 // 2]))

                # scale and truncate

                # note: we truncate rather than round; for the
                # positive data in the window this errs on the side of
                # slightly less energy than if we rounded, but it avoids
                # the problem of rounding making the sum be more than
                # 1 for clients using the 'sum'-to-one normalization

                if norm is None:
                    norm_sum = 1
                elif norm == 'mode':
                    norm_sum = hamming[length1 // 2]
                    assert norm_sum == hamming[length // 2]
                elif norm == 'sum':
                    norm_sum = sum(hamming)
                elif norm == 'sumsq':
                    norm_sum = sqrt(sum(h * h for h in hamming))
                else:
                    assert False, "unreachable"

                assert norm_sum > 0
                norm_scale = float(1 << shift) / norm_sum
                hamming = windows[key] = frozentuple(
                    int(h * norm_scale) for h in hamming)

        assert type(hamming) is frozentuple
        return hamming