Example #1
0
 def to_serializable(self):
     """
     Exports intervals and length of `ArrayInterval` to a serializable object.
     Intervals are exported as `self._intervals_to_str` to be human readable. 
     Allows easy export of `ArrayIntervals`, e.g. into .json format. 
     
     >>> from IPython.lib.pretty import pprint
     >>> from paderbox.array.interval.core import ArrayInterval
     >>> ai = ArrayInterval.from_str('1:4, 5:20, 21:25', shape=50)
     >>> ai
     ArrayInterval("1:4, 5:20, 21:25", shape=(50,))
     >>> ai.to_serializable()
     ('1:4, 5:20, 21:25', (50,))
     """
     intervals = self.normalized_intervals
     if self.inverse_mode:
         intervals = cy_invert_intervals(intervals, self.shape[-1])
     return intervals_to_str(intervals), self.shape
Example #2
0
def test_cy_invert_intervals():
    assert cy_invert_intervals(((1, 2), (3, 4)), 5) == ((0, 1), (2, 3), (4, 5))
    assert cy_invert_intervals(((0, 3), (4, 5)), 5) == ((3, 4), )
    assert cy_invert_intervals(((0, 3), (4, 5)), 6) == ((3, 4), (5, 6))
    assert cy_invert_intervals(((1, 3), (4, 5)), 5) == ((0, 1), (3, 4))
    assert cy_invert_intervals((), 10) == ((0, 10), )
Example #3
0
    def __setitem__(self, item, value):
        """
        >>> ai = zeros(50)
        >>> ai[10:15] = 1
        >>> ai
        ArrayInterval("10:15", shape=(50,))
        >>> ai[5:10] = 1
        >>> ai
        ArrayInterval("5:15", shape=(50,))
        >>> ai[1:4] = 1
        >>> ai
        ArrayInterval("1:4, 5:15", shape=(50,))
        >>> ai[15:20] = 1
        >>> ai
        ArrayInterval("1:4, 5:20", shape=(50,))
        >>> ai[21:25] = 1
        >>> ai
        ArrayInterval("1:4, 5:20, 21:25", shape=(50,))
        >>> ai[10:15] = 1
        >>> ai
        ArrayInterval("1:4, 5:20, 21:25", shape=(50,))
        >>> ai[0:50] = 1
        >>> ai[0:0] = 1
        >>> ai
        ArrayInterval("0:50", shape=(50,))
        >>> ai[3:6]
        array([ True,  True,  True])
        >>> ai[3:6] = np.array([ True,  False,  True])
        >>> ai
        ArrayInterval("0:4, 5:50", shape=(50,))
        >>> ai[10:13] = np.array([ False,  True,  False])
        >>> ai
        ArrayInterval("0:4, 5:10, 11:12, 13:50", shape=(50,))

        >>> ai = zeros(50)
        >>> ai[:] = 1
        >>> ai[10:40] = 0
        >>> ai
        ArrayInterval("0:10, 40:50", shape=(50,))

        >>> ai = zeros(50)
        >>> ai2 = zeros(10)
        >>> ai2[5:10] = 1
        >>> ai[10:20] = ai2
        >>> ai
        ArrayInterval("15:20", shape=(50,))
        >>> ai2 = zeros(20)
        >>> ai2[0:10] = 1
        >>> ai2[15:20] = 1
        >>> ai[10:30] = ai2
        >>> ai
        ArrayInterval("10:20, 25:30", shape=(50,))

        >>> ai[40:60] = ai2
        Traceback (most recent call last):
          ...
        ValueError: Could not broadcast input with length 20 into shape 10
        >>> ai[-20:] = ai2
        >>> ai
        ArrayInterval("10:20, 25:40, 45:50", shape=(50,))

        >>> ai = zeros(20)
        >>> ai[:10] = ones(10)
        >>> ai
        ArrayInterval("0:10", shape=(20,))
        >>> ai = ones(20)
        >>> ai[:10] = zeros(10)
        >>> ai
        ArrayInterval("0:10", shape=(20,), inverse_mode=True)

        """
        if not isinstance(item, slice):
            raise NotImplementedError(
                f'{self.__class__.__name__}.__setitem__ only supports slices '
                f'for indexing, not {item!r}')

        start, stop = cy_parse_item(item, self.shape)

        if np.isscalar(value):
            if value not in (0, 1):
                # Numpy interprets values as boolean even if they are larger
                # than 1. We don't do that here because using other values than
                # boolean (or 0, 1) often indicates a bug or a wrong assumption
                # by the user.
                raise ValueError(
                    f'{self.__class__.__name__} only supports assigning '
                    f'boolean (or 0 or 1) scalar values, not {value!r}')
            value = bool(value)
            if self.inverse_mode:
                value = not value
            if value:
                self.intervals = self.intervals + ((start, stop), )
            else:
                self.intervals = cy_non_intersection((start, stop),
                                                     self.intervals)
        elif isinstance(value, (tuple, list, np.ndarray, ArrayInterval)):
            if not isinstance(value, ArrayInterval):
                # Inverse mode has to be the same as self.inverse_mode to have
                # matching intervals. The value is inverted in
                # ArrayInterval.__init__ if inverse_mode=True
                value = ArrayInterval(value, inverse_mode=self.inverse_mode)

            if len(value) != stop - start:
                raise ValueError(
                    f'Could not broadcast input with length {len(value)} into '
                    f'shape {stop - start}')
            value_intervals = value.intervals
            if value.inverse_mode != self.inverse_mode:
                value_intervals = cy_invert_intervals(value_intervals,
                                                      value.shape[-1])
            intervals = cy_non_intersection((start, stop), self.intervals)
            self.intervals = intervals + tuple([(s + start, e + start)
                                                for s, e in value_intervals])
        else:
            raise NotImplementedError(
                f'{self.__class__.__name__}.__setitem__ not implemented for '
                f'type {type(value)} of {value!r}')