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
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
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
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