diff --git a/firanka/exceptions.py b/firanka/exceptions.py index 5a960dece93dbe1c8ed50b5e08a5f5b07e927c6c..b8ae481e5e3077e4c0bd9ad1ec930ed02f3e00b8 100644 --- a/firanka/exceptions.py +++ b/firanka/exceptions.py @@ -6,6 +6,7 @@ __all__ = [ 'NotInDomainError', ] + class FirankaError(Exception): """ Base class for firanka's exceptions diff --git a/firanka/ranges.py b/firanka/ranges.py index 9e5c64e160e99a9c8612856aa4b5f13adbb53352..a2b2ae17e7812aab1dc9aa98975cdacbf60a2d0b 100644 --- a/firanka/ranges.py +++ b/firanka/ranges.py @@ -17,6 +17,7 @@ def _pre_range(fun): if not isinstance(arg, Range): arg = Range(arg) return fun(self, arg, *args, **kwargs) + return inner @@ -26,7 +27,8 @@ class Range(object): """ def translate(self, x): - return Range(self.start+x, self.stop+x, self.left_inc, self.right_inc) + return Range(self.start + x, self.stop + x, self.left_inc, + self.right_inc) def __init__(self, *args): if len(args) == 1: @@ -38,7 +40,8 @@ class Range(object): stop = rs.stop if rs.stop is not None else float('+inf') args = start, stop, not math.isinf(start), not math.isinf(stop) else: - if rs[0] not in '<(': raise ValueError('Must start with ( or <') + if rs[0] not in '<(': raise ValueError( + 'Must start with ( or <') if rs[-1] not in '>)': raise ValueError('Must end with ) or >') if ';' not in rs: raise ValueError('Separator ; required') @@ -56,18 +59,14 @@ class Range(object): """ :type x: index or a Range """ - if isinstance(x, six.string_types): x = Range(x) if isinstance(x, Range): - if x.start == self.start: - if x.left_inc ^ self.left_inc: - return False - - if x.stop == self.stop: - if x.right_inc ^ self.right_inc: - return False + if ((x.start == self.start) and (x.left_inc ^ self.left_inc)) \ + or ((x.stop == self.stop) and ( + x.right_inc ^ self.right_inc)): + return False return (x.start >= self.start) and (x.stop <= self.stop) else: @@ -80,13 +79,16 @@ class Range(object): return self.start < x < self.stop def is_empty(self): - return (self.start == self.stop) and not (self.left_inc or self.right_inc) + return (self.start == self.stop) and not ( + self.left_inc or self.right_inc) def length(self): return self.stop - self.start def __repr__(self): - return 'Range(%s, %s, %s, %s)' % (repr(self.start), repr(self.stop), repr(self.left_inc), repr(self.right_inc)) + return 'Range(%s, %s, %s, %s)' % ( + repr(self.start), repr(self.stop), repr(self.left_inc), + repr(self.right_inc)) def __getitem__(self, item): if not isinstance(item, slice): diff --git a/firanka/series.py b/firanka/series.py index b59d5df57f5e3843b02889f335c56139aa9d3d98..c1bb0cc140d1d7c6f4210b38ce31a9e983c32a5f 100644 --- a/firanka/series.py +++ b/firanka/series.py @@ -1,4 +1,3 @@ - # coding=UTF-8 from __future__ import print_function, absolute_import, division @@ -129,12 +128,13 @@ class AppliedSeries(Series): class TranslatedSeries(Series): def __init__(self, series, x, *args, **kwargs): - super(TranslatedSeries, self).__init__(self.domain.translate(x), *args, **kwargs) + super(TranslatedSeries, self).__init__(self.domain.translate(x), *args, + **kwargs) self.series = series self.x = x def _get_for(self, item): - return self.series._get_for(item+self.x) + return self.series._get_for(item + self.x) class SlicedSeries(Series): @@ -157,7 +157,6 @@ def _appendif(lst, ptr, v): class DiscreteSeries(Series): - def __init__(self, data, domain=None, *args, **kwargs): if len(data) == 0: domain = EMPTY_SET @@ -169,13 +168,15 @@ class DiscreteSeries(Series): if len(data) > 0: if self.domain.start < data[0][0]: - raise ValueError('some domain space is not covered by definition!') + raise ValueError( + 'some domain space is not covered by definition!') def apply(self, fun): return DiscreteSeries([(k, fun(v)) for k, v in self.data], self.domain) def apply_with_indices(self, fun): - return DiscreteSeries([(k, fun(k, v)) for k, v in self.data], self.domain) + return DiscreteSeries([(k, fun(k, v)) for k, v in self.data], + self.domain) def _get_for(self, item): for k, v in reversed(self.data): @@ -185,7 +186,8 @@ class DiscreteSeries(Series): raise RuntimeError('should never happen') def translate(self, x): - return DiscreteSeries([(k+x, v) for k, v in self.data], self.domain.translate(x)) + return DiscreteSeries([(k + x, v) for k, v in self.data], + self.domain.translate(x)) def _join_discrete_other_discrete(self, series, fun): new_domain = self.domain.intersection(series.domain) @@ -233,15 +235,18 @@ class DiscreteSeries(Series): return self._join_discrete_other_discrete(series, fun) if new_domain.start > self.data[0][0]: - c = [(new_domain.start, fun(self._get_for(new_domain.start), series._get_for(new_domain.start)))] + c = [(new_domain.start, fun(self._get_for(new_domain.start), + series._get_for(new_domain.start)))] else: c = [] - for k, v in ((k, v) for k, v in self.data if new_domain.start <= k <= new_domain.stop): + for k, v in ((k, v) for k, v in self.data if + new_domain.start <= k <= new_domain.stop): _appendif(c, k, fun(v, series._get_for(k))) if c[-1][0] != new_domain.stop: - c.append((new_domain.stop, fun(self._get_for(new_domain.stop), series._get_for(new_domain.stop)))) + c.append((new_domain.stop, fun(self._get_for(new_domain.stop), + series._get_for(new_domain.stop)))) return DiscreteSeries(c, new_domain) @@ -249,8 +254,8 @@ class DiscreteSeries(Series): """Simplify self""" nd = [self.data[0]] for i in six.moves.range(1, len(self.data)): - if self.data[i][1] != nd[-1][1]: - nd.append(self.data[i]) + if self.data[i][1] != nd[-1][1]: + nd.append(self.data[i]) return DiscreteSeries(nd, self.domain) @@ -258,6 +263,7 @@ class FunctionSeries(Series): """ Series with values defined by a function """ + def __init__(self, fun, domain, *args, **kwargs): super(FunctionSeries, self).__init__(domain, *args, **kwargs) self.fun = fun @@ -270,6 +276,7 @@ class JoinedSeries(Series): """ Series stemming from performing an operation on two series """ + def __init__(self, ser1, ser2, op, *args, **kwargs): domain = ser1.domain.intersection(ser2.domain) super(JoinedSeries, self).__init__(domain, *args, **kwargs) @@ -282,7 +289,6 @@ class JoinedSeries(Series): class ModuloSeries(Series): - def __init__(self, series, *args, **kwargs): """ Construct a modulo series diff --git a/firanka/timeproviders.py b/firanka/timeproviders.py index 91d18a5bfac04382cb566bb54aa61ef50a14c825..2cca5f445727763f15fe355218f8806290311fb8 100644 --- a/firanka/timeproviders.py +++ b/firanka/timeproviders.py @@ -3,13 +3,11 @@ from __future__ import print_function, absolute_import, division import six import logging - from .series import Series from .ranges import Range class BijectionMapping(object): - def __init__(self, user2float, float2user): """ :param user2float: callable/1 => float, mapping from your time system to floats @@ -29,11 +27,13 @@ class TimeProvidedSeries(Series): """ If your time is something else than simple floats, this will help you out """ + def __init__(self, series, mapping, *args, **kwargs): """ :param series: series to overlay """ - super(TimeProvidedSeries, self).__init__(series.domain, *args, **kwargs) + super(TimeProvidedSeries, self).__init__(series.domain, *args, + **kwargs) self.mapping = mapping self.series = series @@ -42,8 +42,11 @@ class TimeProvidedSeries(Series): def __getitem__(self, item): if isinstance(item, slice): - item = slice(float('-inf') if slice.start is None else self.to_float(slice.start), - float('+inf') if slice.stop is None else self.to_float(slice.stop),) + item = slice( + float('-inf') if slice.start is None else self.to_float( + slice.start), + float('+inf') if slice.stop is None else self.to_float( + slice.stop), ) return self._withmap(self.series[item]) elif isinstance(item, Range): diff --git a/tests/test_range.py b/tests/test_range.py index f116128a9bff68beb50e39399b8f3f45673de928..5463f9001db84be63bf273a431c9a343b048493a 100644 --- a/tests/test_range.py +++ b/tests/test_range.py @@ -9,10 +9,12 @@ class TestRange(unittest.TestCase): if type(val) == bool: p = Range(a).intersection(b) if p.is_empty() != val: - self.fail('%s ^ %s [=> %s] != %s' % (Range(a), Range(b), p, val)) + self.fail( + '%s ^ %s [=> %s] != %s' % (Range(a), Range(b), p, val)) p = Range(b).intersection(a) if p.is_empty() != val: - self.fail('%s ^ %s [=> %s] != %s' % (Range(b), Range(a), p, val)) + self.fail( + '%s ^ %s [=> %s] != %s' % (Range(b), Range(a), p, val)) else: self.assertEqual(Range(a).intersection(b), Range(val)) self.assertEqual(Range(b).intersection(a), Range(val)) @@ -21,9 +23,9 @@ class TestRange(unittest.TestCase): self.assertTrue(Range('<-5;5>')[0:] == Range('<0;5>')) def test_isempty(self): - self.assertTrue(Range(-1,-1,False,False).is_empty()) - self.assertFalse(Range(-1,-1,False,True).is_empty()) - self.assertEqual(Range(0,0,False,False), Range(2,2,False,False)) + self.assertTrue(Range(-1, -1, False, False).is_empty()) + self.assertFalse(Range(-1, -1, False, True).is_empty()) + self.assertEqual(Range(0, 0, False, False), Range(2, 2, False, False)) def test_intersection(self): self.do_intersect('<-10;1>', '<2;3>', True) @@ -34,8 +36,8 @@ class TestRange(unittest.TestCase): self.do_intersect('<-5;5>', '(-5;5)', '(-5;5)') def test_str_and_repr_and_bool(self): - p = Range(-1,1,True,True) - self.assertEqual(eval(repr(p)),p) + p = Range(-1, 1, True, True) + self.assertEqual(eval(repr(p)), p) self.assertEqual(str(Range(-1, 1, True, True)), '<-1;1>') def test_constructor(self): diff --git a/tests/test_series.py b/tests/test_series.py index 1b45267efa8ac2526203d5eadea89286d8ff9244..8b8a0221fd20a967034bdcc9458c60ad4bd5fe12 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -9,13 +9,15 @@ from firanka.exceptions import NotInDomainError NOOP = lambda x: x -class TestDiscreteSeries(unittest.TestCase): +class TestDiscreteSeries(unittest.TestCase): def test_uncov(self): - self.assertRaises(ValueError, lambda: DiscreteSeries([[0,0], [1,1], [2,2]], '<-5;2>')) + self.assertRaises(ValueError, + lambda: DiscreteSeries([[0, 0], [1, 1], [2, 2]], + '<-5;2>')) def test_base(self): - s = DiscreteSeries([[0,0], [1,1], [2,2]]) + s = DiscreteSeries([[0, 0], [1, 1], [2, 2]]) self.assertEqual(s[0], 0) self.assertEqual(s[0.5], 0) @@ -24,7 +26,8 @@ class TestDiscreteSeries(unittest.TestCase): self.assertRaises(NotInDomainError, lambda: s[-1]) self.assertRaises(NotInDomainError, lambda: s[2.5]) - s = DiscreteSeries([[0,0], [1,1], [2,2]], domain=Range(0,3,True,True)) + s = DiscreteSeries([[0, 0], [1, 1], [2, 2]], + domain=Range(0, 3, True, True)) self.assertEqual(s[0], 0) self.assertEqual(s[0.5], 0) self.assertEqual(s[1], 1) @@ -33,7 +36,7 @@ class TestDiscreteSeries(unittest.TestCase): self.assertEqual(s[2.5], 2) def test_translation(self): - s = DiscreteSeries([[0,0], [1,1], [2,2]]).translate(3) + s = DiscreteSeries([[0, 0], [1, 1], [2, 2]]).translate(3) self.assertEqual(s[3], 0) self.assertEqual(s[3.5], 0) @@ -60,55 +63,59 @@ class TestDiscreteSeries(unittest.TestCase): sa = DiscreteSeries([[0, 0], [1, 1], [2, 2]]) sb = DiscreteSeries([[0, 1], [1, 2], [2, 3]]) - sc = sa.join_discrete(sb, lambda a, b: a+b) + sc = sa.join_discrete(sb, lambda a, b: a + b) self.assertIsInstance(sc, DiscreteSeries) - self.assertEqual(sc.eval_points([0,1,2]), [1,3,5]) - self.assertEqual(sc.data, [(0,1),(1,3),(2,5)]) + self.assertEqual(sc.eval_points([0, 1, 2]), [1, 3, 5]) + self.assertEqual(sc.data, [(0, 1), (1, 3), (2, 5)]) def test_eval2(self): sa = DiscreteSeries([[0, 0], [1, 1], [2, 2]]) sb = FunctionSeries(NOOP, '<0;2>') - sc = sa.join_discrete(sb, lambda a, b: a+b) - self.assertEqual(sc.eval_points([0,1,2]), [0,2,4]) + sc = sa.join_discrete(sb, lambda a, b: a + b) + self.assertEqual(sc.eval_points([0, 1, 2]), [0, 2, 4]) self.assertIsInstance(sc, DiscreteSeries) - self.assertEqual(sc.data, [(0,0),(1,2),(2,4)]) + self.assertEqual(sc.data, [(0, 0), (1, 2), (2, 4)]) def test_apply(self): - sa = DiscreteSeries([[0, 0], [1, 1], [2, 2]]).apply(lambda x: x+1) - self.assertEquals(sa.data, [(0,1),(1,2),(2,3)]) + sa = DiscreteSeries([[0, 0], [1, 1], [2, 2]]).apply(lambda x: x + 1) + self.assertEquals(sa.data, [(0, 1), (1, 2), (2, 3)]) - sb = DiscreteSeries([[0, 0], [1, 1], [2, 2]]).apply_with_indices(lambda k,v: k) - self.assertEquals(sb.data, [(0,0),(1,1),(2,2)]) + sb = DiscreteSeries([[0, 0], [1, 1], [2, 2]]).apply_with_indices( + lambda k, v: k) + self.assertEquals(sb.data, [(0, 0), (1, 1), (2, 2)]) def test_eval3(self): - sa = FunctionSeries(lambda x: x**2, '<-10;10)') + sa = FunctionSeries(lambda x: x ** 2, '<-10;10)') sb = FunctionSeries(NOOP, '<0;2)') - sc = sa.join(sb, lambda a, b: a*b) + sc = sa.join(sb, lambda a, b: a * b) - PTS = [0,1,1.9] - EPTS = [x*x**2 for x in PTS] + PTS = [0, 1, 1.9] + EPTS = [x * x ** 2 for x in PTS] self.assertEqual(sc.eval_points(PTS), EPTS) self.assertTrue(Range('<0;2)') in sc.domain) def test_discretize(self): # note the invalid data for covering this domain - self.assertRaises(ValueError, lambda: FunctionSeries(lambda x: x**2, '<-10;10)').discretize([0,1,2,3,4,5], '(-1;6)')) + self.assertRaises(ValueError, lambda: FunctionSeries(lambda x: x ** 2, + '<-10;10)').discretize( + [0, 1, 2, 3, 4, 5], '(-1;6)')) - PTS = [-1, 0,1,2,3,4,5] - sa = FunctionSeries(lambda x: x**2, '<-10;10)').discretize(PTS, '(-1;6)') + PTS = [-1, 0, 1, 2, 3, 4, 5] + sa = FunctionSeries(lambda x: x ** 2, '<-10;10)').discretize(PTS, + '(-1;6)') self.assertIsInstance(sa, DiscreteSeries) - self.assertEqual(sa.data, [(i, i**2) for i in PTS]) + self.assertEqual(sa.data, [(i, i ** 2) for i in PTS]) - sa = FunctionSeries(lambda x: x**2, '<-10;10)').discretize(PTS) + sa = FunctionSeries(lambda x: x ** 2, '<-10;10)').discretize(PTS) self.assertIsInstance(sa, DiscreteSeries) - self.assertEqual(sa.data, [(i, i**2) for i in PTS]) + self.assertEqual(sa.data, [(i, i ** 2) for i in PTS]) - empty = FunctionSeries(lambda x: x**2, '<-10;10)').discretize([]) + empty = FunctionSeries(lambda x: x ** 2, '<-10;10)').discretize([]) self.assertTrue(empty.domain.is_empty()) @@ -125,31 +132,37 @@ class TestFunctionSeries(unittest.TestCase): self.assertEqual(sp.domain.stop, 1.5) def test_apply(self): - PTS = [-1,-2,-3,1,2,3] - series = FunctionSeries(NOOP, '<-5;5>').apply(lambda x: x*2) + PTS = [-1, -2, -3, 1, 2, 3] + series = FunctionSeries(NOOP, '<-5;5>').apply(lambda x: x * 2) - self.assertEqual(series.eval_points(PTS), [x*2 for x in PTS]) + self.assertEqual(series.eval_points(PTS), [x * 2 for x in PTS]) - PTS = [-1,-2,-3,1,2,3] - series = FunctionSeries(NOOP, '<-5;5>').apply_with_indices(lambda k, x: k) + PTS = [-1, -2, -3, 1, 2, 3] + series = FunctionSeries(NOOP, '<-5;5>').apply_with_indices( + lambda k, x: k) self.assertEqual(series.eval_points(PTS), [x for x in PTS]) def test_domain_sensitivity(self): logs = FunctionSeries(math.log, '(0;5>') - dirs = DiscreteSeries([(0,1),(1,2),(3,4)], '<0;5>') + dirs = DiscreteSeries([(0, 1), (1, 2), (3, 4)], '<0;5>') - self.assertRaises(ValueError, lambda: dirs.join_discrete(logs, lambda x, y: x+y)) + self.assertRaises(ValueError, + lambda: dirs.join_discrete(logs, lambda x, y: x + y)) -class TestModuloSeries(unittest.TestCase): +class TestModuloSeries(unittest.TestCase): def test_exceptions(self): - self.assertRaises(ValueError, lambda: ModuloSeries(FunctionSeries(NOOP, '(-inf; 0>'))) - self.assertRaises(ValueError, lambda: ModuloSeries(FunctionSeries(NOOP, '(-inf; inf)'))) - self.assertRaises(ValueError, lambda: ModuloSeries(FunctionSeries(NOOP, '<0; 0>'))) + self.assertRaises(ValueError, lambda: ModuloSeries( + FunctionSeries(NOOP, '(-inf; 0>'))) + self.assertRaises(ValueError, lambda: ModuloSeries( + FunctionSeries(NOOP, '(-inf; inf)'))) + self.assertRaises(ValueError, + lambda: ModuloSeries(FunctionSeries(NOOP, '<0; 0>'))) def test_base(self): - series = ModuloSeries(DiscreteSeries([(0,1),(1,2),(2,3)], '<0;3)')) + series = ModuloSeries( + DiscreteSeries([(0, 1), (1, 2), (2, 3)], '<0;3)')) self.assertEquals(series[3], 1) self.assertEquals(series[4], 2) @@ -157,8 +170,7 @@ class TestModuloSeries(unittest.TestCase): self.assertEquals(series[-1], 3) def test_comp_discrete(self): - ser1 = ModuloSeries(FunctionSeries(lambda x: x**2, '<0;3)')) + ser1 = ModuloSeries(FunctionSeries(lambda x: x ** 2, '<0;3)')) ser2 = FunctionSeries(NOOP, '<0;3)') - ser3 = ser1.join(ser2, lambda x, y: x*y) - + ser3 = ser1.join(ser2, lambda x, y: x * y) diff --git a/tests/test_timeproviders.py b/tests/test_timeproviders.py index eeb784991781e4f58309bf9e5d535f48893085be..d6d0d78c56f0aec503e4eab6090eb045d964e10e 100644 --- a/tests/test_timeproviders.py +++ b/tests/test_timeproviders.py @@ -8,14 +8,13 @@ from firanka.timeproviders import TimeProvidedSeries, BijectionMapping class TestTimeproviders(unittest.TestCase): - def test_base(self): map = BijectionMapping( lambda hhmm: hhmm[0] * 60 + hhmm[1], lambda t: (t // 60, t % 60) ) - ser = DiscreteSeries([(0,17), (60, 20), (120, 18)]) + ser = DiscreteSeries([(0, 17), (60, 20), (120, 18)]) ts = TimeProvidedSeries(ser, map) self.assertEqual(ts[(2, 0)], 18)