コード例 #1
0
def test_update_with_obj_autoremove():
    begin_update_count = 0

    def begin_update(domain):
        nonlocal begin_update_count
        begin_update_count += 1

    end_update_count = 0

    def end_update(domain):
        nonlocal end_update_count
        end_update_count += 1

    f = Curve()

    # Add and remove observer using object
    obj = T()
    f.add_observer(obj, begin=begin_update, end=end_update, autoremove=True)

    f.begin_update(Interval(1, 3))
    assert begin_update_count == 1
    f.end_update(Interval(1, 3))
    assert end_update_count == 1

    obj = None
    f.begin_update(Interval(1, 3))
    assert begin_update_count == 1
    f.end_update(Interval(1, 3))
    assert end_update_count == 1
コード例 #2
0
def test_first():
    funcs = [[(0, None), (1, 12), (2, None)], [(0, 1), (1, 1), (2, 1)]]
    first = Curve.first(funcs)
    assert first(-1) is None
    assert first(0) == 1
    assert first(1) == 12
    assert first(2) == 1
    assert first(3) is None

    funcs = [[(0, None), (1, 12), (2, None)], 1]
    first = Curve.first(funcs)
    assert first(-1) == 1
    assert first(0) == 1
    assert first(1) == 12
    assert first(2) == 1
    assert first(3) == 1

    first = Curve.first([
        Generic(lambda x: 1, domain=Interval(0, 2)),
        Generic(lambda x: 2, domain=Interval.gte(1))
    ])
    assert first(-1) is None
    assert first(0) == 1
    assert first(1) == 1
    assert first(2) == 1
    assert first(2.1) == 2
    assert first(3) == 2
    assert first.sample_points(Interval(0, 3), min_step=1) == [(0, 1), (1, 1),
                                                               (2, 1), (3, 2)]
コード例 #3
0
ファイル: interval_test.py プロジェクト: diatche/intervalpy
def test_round():
    assert Interval(1.2, 3.4).round() == (1, 3)
    assert Interval(1.2, 3.4).round(method=math.floor) == (1, 3)
    assert Interval(1.2, 3.4).round(method=math.ceil) == (2, 4)
    assert Interval.open_closed(1.2, 3.4).round() == Interval.open_closed(1, 3)
    assert Interval.closed_open(1.2, 3.4).round() == Interval.closed_open(1, 3)
    assert Interval.empty().round() == Interval.empty()
コード例 #4
0
ファイル: tangent.py プロジェクト: diatche/curvepy
    def update_extension(self):
        if self.start:
            x = self.curve.domain.start
            if x is not None and self.curve.domain.start_open and self.curve.domain.contains(x + self.min_step):
                x += self.min_step
            y = None
            d_y = None
            if self.regression_degree is not None:
                x1 = x
                for i in range(self.regression_degree):
                    x1 = self.curve.x_next(x1, min_step=self.min_step)
                domain = Interval(x, x1)
                tangent = self.curve.regression(domain, min_step=self.min_step)
                if tangent is not None:
                    y = tangent.y(x)
                    d_y = tangent.slope
            elif self.regression_period is not None:
                domain = Interval(x, x + self.regression_period)
                tangent = self.curve.regression(domain, min_step=self.min_step)
                if tangent is not None:
                    y = tangent.y(x)
                    d_y = tangent.slope
            else:
                y = self.curve.y(x)
                d_y = self.curve.d_y(x, forward=True)

            self.start_valid = y is not None and d_y is not None
            if self.start_valid:
                self.update_extension_func(self.start_func, x, y, d_y)

        if self.end:
            x = self.curve.domain.end
            if x is not None and self.curve.domain.end_open and self.curve.domain.contains(x - self.min_step):
                x -= self.min_step
            y = None
            d_y = None
            if self.regression_degree is not None:
                x0 = x
                for i in range(self.regression_degree):
                    x0 = self.curve.x_previous(x0, min_step=self.min_step)
                domain = Interval(x0, x)
                tangent = self.curve.regression(domain, min_step=self.min_step)
                if tangent is not None:
                    y = tangent.y(x)
                    d_y = tangent.slope
            elif self.regression_period is not None:
                domain = Interval(x - self.regression_period, x)
                tangent = self.curve.regression(domain, min_step=self.min_step)
                if tangent is not None:
                    y = tangent.y(x)
                    d_y = tangent.slope
            else:
                y = self.curve.y(x)
                d_y = self.curve.d_y(x, forward=False)

            self.end_valid = y is not None and d_y is not None
            if self.end_valid:
                self.update_extension_func(self.end_func, x, y, d_y)
コード例 #5
0
ファイル: points.py プロジェクト: diatche/curvepy
    def append_list(self, points):
        """
        `points` are assumed to be strictly ordered in ascending order w.r.t. to `x`.
        """
        points_len = len(self._points)
        if points_len == 0:
            return self.set(points)
        new_points_len = len(points)
        if new_points_len == 0:
            return

        if points[0][0] <= self._points[-1][0]:
            raise Exception(
                'Attempting to append points in non-ascending order')

        if self.domain.is_empty:
            domain = Interval.closed(points[0][0], points[-1][0])
        else:
            domain = Interval(self.domain.end,
                              points[-1][0],
                              start_open=True,
                              end_open=False)
        self.begin_update(domain)
        self._is_equally_spaced = self._points_equally_spaced(
            self._points, points)
        if self._force_equally_spaced and not self._is_equally_spaced:
            raise Exception(
                'Attempting to append points at non-regular intervals: {}{} + {}{}'
                .format('...' if len(self._points) > 2 else '',
                        self._points[len(self._points) - 2:], points[:2],
                        '...' if len(points) > 2 else ''))
        self._points += points
        self._did_change_points()
        self.end_update(domain)
コード例 #6
0
ファイル: points.py プロジェクト: diatche/curvepy
 def get_domain(self):
     if len(self._points) == 0:
         return Interval.empty()
     return Interval(self._points[0][0],
                     self._points[-1][0],
                     start_open=False,
                     end_open=False)
コード例 #7
0
    def span_interval(self, interval, start_open=False) -> Interval:
        """
        Returns the time interval which fully contains the specified interval.
        """
        interval = Interval.parse(interval, default_inf=True)
        if interval.is_empty:
            return Interval.empty()
        elif interval.start == interval.end:
            return self.span_date(interval.start, start_open=start_open)

        end_open = not start_open

        if interval.is_negative_infinite:
            start = -math.inf
        else:
            # Move outward if interval is closed but should be open
            o = not interval.start_open and start_open
            span = self.span_date(interval.start, start_open=o)
            start = span.start

        if interval.is_positive_infinite:
            end = math.inf
        else:
            # Move outward if interval is closed but should be open
            o = not interval.end_open and end_open
            span = self.span_date(interval.end, start_open=not o)
            end = span.end

        return Interval(start,
                        end,
                        start_open=start_open,
                        end_open=not start_open)
コード例 #8
0
ファイル: quote.py プロジェクト: diatche/curvepy
 def domain(self):
     if self._domain is None:
         self._domain = Interval(self.start_date,
                                 self.end_date,
                                 start_open=DOMAIN_START_OPEN,
                                 end_open=not DOMAIN_START_OPEN)
     return self._domain
コード例 #9
0
    def _calendar_span(self, date, start_open=False) -> Interval:
        """
        Returns the time interval which contains the specified `date`.
        """
        date = arrow.get(date)
        t = self._normalized_date(date)
        msec = timedelta(microseconds=1)
        start = date - msec
        end = date + msec
        degree = self.degree
        unit = self.unit
        sunit = type(self).singular_unit(unit)
        date_span = None

        force_agr = unit == WEEKS
        if force_agr:
            # Special case
            sunit = type(self).singular_unit(DAYS)

        # Find matching unit interval (1d, 1h, etc)
        for r0, r1 in arrow.Arrow.span_range(sunit, start, end):
            # Normalize range end
            r1 += msec
            interval = Interval(r0.float_timestamp,
                                r1.float_timestamp,
                                start_open=start_open,
                                end_open=not start_open)
            if interval.contains(t):
                if degree == 1 and not force_agr:
                    return interval
                else:
                    date_span = r0, r1
                    break

        # Expand into aggregate interval
        if self.unit == YEARS:
            start_date, end_date = self._expand_years(date_span)
        elif self.parent is not None and self.parent.unit == YEARS:
            start_date, end_date = self._expand_within_year(date_span)
        else:
            raise Exception(f'Unable to expand unit: {self.unit}')

        return Interval(self._normalized_date(start_date),
                        self._normalized_date(end_date),
                        start_open=start_open,
                        end_open=not start_open)
コード例 #10
0
ファイル: interval_test.py プロジェクト: diatche/intervalpy
def test_equals():
    d = Interval(1, 3)
    assert d.equals((1, 3))
    assert not d.equals(None)
    assert not d.equals(Interval.closed_open(1, 3))
    assert Interval.empty().equals(Interval.empty())
    # Empty intervals are always equal
    assert Interval.open(1, 1).equals(Interval.open(2, 2)) 
    assert Interval.infinite().equals(Interval.infinite())
コード例 #11
0
ファイル: interval_test.py プロジェクト: diatche/intervalpy
def test_subset():
    d = Interval(1, 3)
    assert d.is_subset_of((0, 4))
    assert d.is_subset_of((1, 3))
    assert not d.is_subset_of(Interval.closed_open(1, 3))

    assert d.is_superset_of((2, 2))
    assert d.is_superset_of((1, 3))
    assert d.is_superset_of(Interval.closed_open(1, 3))
コード例 #12
0
    def _did_update_extremas(self):
        self.possible_extrema = None
        self.possible_extrema_phase = None

        if len(self.extremas) == 0:
            self.extrema_interval = Interval.empty()
        else:
            self.extrema_interval = Interval(self.extrema_xs[0],
                                             self.extrema_xs[-1],
                                             start_open=False,
                                             end_open=False)
コード例 #13
0
 def _offset_interval(self, domain, floor=False):
     start = self._offset_x(domain.start, floor=floor)
     end = self._offset_x(domain.end, floor=floor)
     if start is None and end is None:
         return Interval.empty()
     elif start is None:
         return Interval(start,
                         end,
                         start_open=False,
                         end_open=domain.end_open)
     elif end is None:
         return Interval(start,
                         end,
                         start_open=domain.start_open,
                         end_open=False)
     else:
         return Interval(start,
                         end,
                         start_open=domain.start_open,
                         end_open=domain.end_open)
コード例 #14
0
            def next_uniform_span():
                nonlocal start, step, i, count

                if i == count:
                    return None
                a = start + i * step
                b = a + step
                i += 1
                return Interval(min(a, b),
                                max(a, b),
                                start_open=start_open,
                                end_open=not start_open)
コード例 #15
0
 def next_span():
     nonlocal x1, count
     if limit is not None and count >= limit:
         return None
     count += 1
     x0 = x1
     x1 = self.step(x0, count=size, backward=backward)
     span = Interval(min(x0, x1),
                     max(x0, x1),
                     start_open=start_open,
                     end_open=not start_open)
     return span
コード例 #16
0
ファイル: curve.py プロジェクト: diatche/curvepy
 def get_range(self, domain=None, **kwargs):
     points = self.sample_points(domain=domain, **kwargs)
     low = None
     high = None
     for p in points:
         if low is None or p[1] < low:
             low = p[1]
         if high is None or p[1] > high:
             high = p[1]
     if low is None or high is None:
         return Interval.empty()
     return Interval(low, high)
コード例 #17
0
ファイル: interval_test.py プロジェクト: diatche/intervalpy
def test_partition():
    ds = Interval(1, 3).partition([2])
    assert list(map(tuple, ds)) == [(1, 2), (2, 3)]
    assert not ds[0].start_open
    assert ds[0].end_open
    assert not ds[1].start_open
    assert not ds[1].end_open

    ds = Interval(0, 3).partition([0, 1, 2, 3, 4], start_open=True)
    assert list(map(tuple, ds)) == [(0, 0), (0, 1), (1, 2), (2, 3)]
    assert not ds[0].start_open
    assert not ds[0].end_open
    assert ds[1].start_open
    assert not ds[1].end_open

    ds = Interval(0, 3).partition([0, 1, 2, 3, 4], start_open=False)
    assert list(map(tuple, ds)) == [(0, 1), (1, 2), (2, 3), (3, 3)]
    assert not ds[0].start_open
    assert ds[0].end_open
    assert not ds[1].start_open
    assert ds[1].end_open
コード例 #18
0
ファイル: util.py プロジェクト: diatche/pyduration
def timespan(t1, t2, open=None, start_open=None, end_open=None):
    t1 = timestamp(t1)
    t2 = timestamp(t2)
    if open is not None:
        start_open = bool(open)
        end_open = bool(open)
    elif start_open is not None:
        start_open = bool(start_open)
        end_open = not bool(start_open)
    elif end_open is not None:
        start_open = not bool(end_open)
        end_open = bool(end_open)
    return Interval(t1, t2, start_open=start_open, end_open=end_open)
コード例 #19
0
ファイル: aggregate_test.py プロジェクト: diatche/curvepy
def test_duplicate_multiple_nested_function_update():
    points = Points([])
    f = (points * 0.5 + points * 0.5) * 2

    points.append((0, 1))
    assert f.is_updating is False
    assert f.domain == Interval.point(0)
    assert f.y(0) == 2

    points.append((1, 1))
    assert f.is_updating is False
    assert f.domain == Interval(0, 1)
    assert f.y(1) == 2
コード例 #20
0
ファイル: points.py プロジェクト: diatche/curvepy
    def reset(self, domain=None):
        points_len = len(self._points)
        if points_len == 0:
            return
        if domain is None:
            return self.set([])
        domain = Interval.parse(domain)

        if not self.domain.intersects(domain):
            return

        if domain.is_superset_of(self.domain):
            self.set([])
            return

        remove_start_i, remove_end_i = self._domain_indexes(domain)
        if remove_start_i == remove_end_i:
            # Nothing to remove
            return
        head = self._points[:remove_start_i]
        tail = self._points[remove_end_i:]
        if len(head) != 0 and domain.contains(head[-1][0]):
            del head[-1]
        if len(tail) != 0 and domain.contains(tail[0][0]):
            del tail[0]
        head_len = len(head)
        tail_len = len(tail)
        if head_len + tail_len == 0:
            self.set([])
            return
        points = head + tail

        update_start = self._points[0][0]
        update_start_open = False
        if head_len != 0:
            update_start = head[-1][0]
            update_start_open = True

        update_end = self._points[-1][0]
        update_end_open = False
        if tail_len != 0:
            update_end = tail[0][0]
            update_end_open = True

        update_domain = Interval(update_start,
                                 update_end,
                                 start_open=update_start_open,
                                 end_open=update_end_open)

        self.set(points, update_domain=update_domain)
コード例 #21
0
def test_constant_step():
    c1 = Constant(2)
    c2 = Constant(3)
    ds = Interval(0, 3).partition([2])
    pw = Piecewise([c1, c2], ds)
    assert pw.domain.start == 0
    assert pw.domain.end == 3
    assert pw(-0.1) is None
    assert pw(0) == 2
    assert pw(1.9) == 2
    assert pw(2) == 3
    assert pw(3) == 3
    assert pw(3.1) is None
    assert np.allclose(pw.sample_points(domain=(0, 3), step=1), [(0, 2), (1, 2), (2, 3), (3, 3)])
コード例 #22
0
def test_varying_step():
    c1 = Constant(2)
    c2 = Points(test_util.point_gen([3, 4], t_start=2))
    ds = Interval(1, 3).partition([2])
    pw = Piecewise([c1, c2], ds)
    assert pw.domain.start == 1
    assert pw.domain.end == 3
    assert pw(0.9) is None
    assert pw(1) == 2
    assert pw(1.9) == 2
    assert pw(2) == 3
    assert pw(3) == 4
    assert pw(3.1) is None
    assert np.allclose(pw.sample_points(domain=(0, 3), step=0.5), [(1, 2), (1.5, 2), (2, 3), (2.5, 3.5), (3, 4)])
コード例 #23
0
ファイル: aggregate_test.py プロジェクト: diatche/curvepy
def test_duplicate_function_update():
    points = Points([])
    f = points + points

    points.append((0, 1))
    assert points.is_updating is False
    assert f.is_updating is False
    assert f.domain == Interval.point(0)
    assert f.y(0) == 2

    points.append((1, 1))
    assert points.is_updating is False
    assert f.is_updating is False
    assert f.domain == Interval(0, 1)
    assert f.y(1) == 2
コード例 #24
0
    def pad(self, interval, start=0, end=0, start_open=False) -> Interval:
        """
        Appends calendar lengths to the start and end of a interval.
        """
        interval = self.span_interval(interval, start_open=start_open)
        if interval.is_empty:
            return Interval.empty()

        l = interval.start
        if not interval.is_negative_infinite:
            l = self.step(l, count=start, backward=True)

        h = interval.end
        if not interval.is_positive_infinite:
            h = self.step(h, count=end)

        return Interval(l, h, start_open=start_open, end_open=not start_open)
コード例 #25
0
ファイル: interval_test.py プロジェクト: diatche/intervalpy
def test_extensions():
    d = Interval(1, 3)
    assert d.get_lte().equals(Interval.lte(3))
    assert d.get_gte().equals(Interval.gte(1))
    assert d.get_lt().equals(Interval.lt(1))
    assert d.get_gt().equals(Interval.gt(3))

    d = Interval.open(1, 3)
    assert d.get_lte().equals(Interval.lt(3))
    assert d.get_gte().equals(Interval.gt(1))
    assert d.get_lt().equals(Interval.lte(1))
    assert d.get_gt().equals(Interval.gte(3))

    d = Interval.empty()
    assert d.get_lte().is_empty
    assert d.get_gte().is_empty
    assert d.get_lt().is_empty
    assert d.get_gt().is_empty
コード例 #26
0
ファイル: interval_test.py プロジェクト: diatche/intervalpy
def test_parse():
    d = Interval.parse(Interval(0, 1, start_open=True, end_open=True))
    assert d.start == 0
    assert d.end == 1
    assert d.start_open
    assert d.end_open

    d = Interval.parse((0, 1))
    assert d.start == 0
    assert d.end == 1
    assert not d.start_open
    assert not d.end_open

    d = Interval.parse(1)
    assert d.start == 1
    assert d.end == 1
    assert not d.start_open
    assert not d.end_open

    with pytest.raises(Exception):
        _ = Interval.parse(None)
    with pytest.raises(Exception):
        _ = Interval.parse(None, default_inf=False)
    assert Interval.parse(None, default_inf=True) == Interval.infinite()

    d = Interval.parse(math.inf)
    assert math.isinf(d.start)
    assert math.isinf(d.end)
    assert d.start > 0
    assert d.end > 0
    assert not d.is_negative_infinite
    assert not d.is_positive_infinite

    d = Interval.parse(-math.inf)
    assert math.isinf(d.start)
    assert math.isinf(d.end)
    assert d.start < 0
    assert d.end < 0
    assert not d.is_negative_infinite
    assert not d.is_positive_infinite

    d = Interval.parse([])
    assert d.is_empty
コード例 #27
0
ファイル: quote.py プロジェクト: diatche/curvepy
    def missing_domains(cls, quotes, domain=None):
        # TODO: optimise by recursively dividing quotes
        # in half and checking if the quotes are
        # contiguous. Then collect domains between
        # contiguous quotes.
        quotes_len = len(quotes)
        if quotes_len == 0:
            if domain is None:
                return []
            else:
                return [domain]

        if domain is None:
            domain = cls.list_domain(quotes)
        else:
            domain = Interval.parse(domain)
        if domain.is_empty:
            return []

        missing_list = []
        head = Interval.intersection([domain, quotes[0].domain.get_lt()])
        if not head.is_empty:
            missing_list.append(head)

        for i in range(1, quotes_len):
            q0 = quotes[i - 1]
            q1 = quotes[i]
            if q0.end_date != q1.start_date:
                if q0.end_date > q1.start_date:
                    continue
                missing = Interval(q0.domain.end,
                                   q1.domain.start,
                                   start_open=not q0.domain.end_open,
                                   end_open=not q1.domain.start_open)
                missing_list.append(missing)

        tail = Interval.intersection([domain, quotes[-1].domain.get_gt()])
        if not tail.is_empty:
            missing_list.append(tail)

        return missing_list
コード例 #28
0
    def _non_calendar_span(self, date, start_open=False) -> Interval:
        # We can use seconds
        coef = self._seconds_coef()
        t = self._normalized_date(date) * coef

        if self.degree == 1:
            # Do not limit to parent for speed
            parent_start = 0
            parent_secs = math.inf
        else:
            # Start from parent start
            parent_span = self.parent.span_date(date, start_open=start_open)
            parent_start = parent_span.start * coef
            parent_secs = parent_span.length * coef

        seconds = self.ave_seconds * coef
        parent_t = t - parent_start
        start = math.floor(parent_t / seconds) * seconds
        end = math.ceil(parent_t / seconds) * seconds

        if start == end:
            if start_open:
                start -= seconds
            else:
                end += seconds

        # Limit to parent end
        if end > parent_secs:
            end = parent_secs

        start_date = parent_start + start
        end_date = parent_start + end

        start_date /= coef
        end_date /= coef

        return Interval(start_date,
                        end_date,
                        start_open=start_open,
                        end_open=not start_open)
コード例 #29
0
def test_func_update():
    begin_update_count = 0
    begin_update_interval = None

    def begin_update(domain):
        nonlocal begin_update_count
        nonlocal begin_update_interval
        begin_update_count += 1
        begin_update_interval = domain

    end_update_count = 0
    end_update_interval = None

    def end_update(domain):
        nonlocal end_update_count
        nonlocal end_update_interval
        end_update_count += 1
        end_update_interval = domain

    f = Curve()
    t = f.add_observer(domain=(0, 2), begin=begin_update, end=end_update)

    f.begin_update(Interval(1, 3))
    assert begin_update_count == 1
    assert end_update_count == 0
    assert begin_update_interval.start == 1
    assert begin_update_interval.end == 3
    f.end_update(Interval(1, 3))
    assert begin_update_count == 1
    assert end_update_count == 1
    assert end_update_interval.start == 1
    assert end_update_interval.end == 3

    f.begin_update(Interval(3, 4))
    assert begin_update_count == 1
    assert end_update_count == 1
    f.end_update(Interval(3, 4))
    assert begin_update_count == 1
    assert end_update_count == 1

    f.remove_observer(t)
    f.begin_update(Interval(1, 3))
    assert begin_update_count == 1
    assert end_update_count == 1
    f.end_update(Interval(1, 3))
    assert begin_update_count == 1
    assert end_update_count == 1
コード例 #30
0
def span(t1, t2, start_open=False):
    return Interval(t_(t1),
                    t_(t2),
                    start_open=start_open,
                    end_open=not start_open)