Example #1
0
    def __and__(self, other):
        """
        >>> a1 = ArrayInterval([True, True, False, False])
        >>> a2 = ArrayInterval([True, False, True, False])
        >>> print(a1 & a2, (a1 & a2)[:])
        ArrayInterval("0:1", shape=(4,)) [ True False False False]
        >>> a1 = ArrayInterval([True, True, False, False], inverse_mode=True)
        >>> a2 = ArrayInterval([True, False, True, False], inverse_mode=True)
        >>> print(a1 & a2, (a1 & a2)[:])
        ArrayInterval("1:4", shape=(4,), inverse_mode=True) [ True False False False]

        >>> np.logical_and(a1, a2)
        array([ True, False, False, False])
        """
        if not isinstance(other, ArrayInterval):
            return NotImplemented
        elif self.inverse_mode is True and other.inverse_mode is True:
            # short circuit
            return ~((~self) | (~other))
        elif self.inverse_mode is False and other.inverse_mode is False:
            if other.shape != self.shape:
                raise ValueError(
                    f'Cannot broadcast together ArrayIntervals with shapes '
                    f'{self.shape} {other.shape}')
            ai = zeros(shape=self.shape)

            normalized_intervals = self.normalized_intervals
            intervals = []
            for (start, stop) in other.normalized_intervals:
                intervals.extend(
                    cy_intersection((start, stop), normalized_intervals))

            ai.intervals = intervals
            return ai
        else:
            raise NotImplementedError(self.inverse_mode, other.inverse_mode)
Example #2
0
def test_cy_intersection():
    assert cy_intersection((0, 3), ((1, 2), )) == ((1, 2), )
    assert cy_intersection((1, 4), ((0, 2), (3, 5))) == ((1, 2), (3, 4))
    assert cy_intersection((1, 2), ((0, 3), )) == ((1, 2), )
    assert cy_intersection((4, 5), ((0, 3), )) == ()
Example #3
0
    def __getitem__(self, item):
        """

        >>> ai = zeros(50)
        >>> ai[19:26]
        array([False, False, False, False, False, False, False])
        >>> ai[10:20] = 1
        >>> ai[25:30] = 1
        >>> ai
        ArrayInterval("10:20, 25:30", shape=(50,))
        >>> ai[19:26]
        array([ True, False, False, False, False, False,  True])
        >>> ai[19]
        True
        >>> ai[5]
        False
        >>> ai[49]
        False
        >>> ai[29]
        True
        >>> ai[-25:-20]
        array([ True,  True,  True,  True,  True])

        Get a similar behavior to numpy when indexing outside of shape:
        >>> ai[-1:1]
        array([], dtype=bool)
        >>> ai[-10:]
        array([False, False, False, False, False, False, False, False, False,
               False])
        >>> ai[45:100]
        array([False, False, False, False, False])

        """
        if isinstance(item, (int, np.integer)):
            index = item
            if index < 0:
                if self.shape is None:
                    raise ValueError(
                        f'Negative indices can only be used on ArrayIntervals '
                        f'with a shape! index={index}')
                index = index + self.shape[-1]
            if index < 0 or self.shape is not None and index > self.shape[-1]:
                raise IndexError(
                    f'Index {item} is out of bounds for ArrayInterval with '
                    f'shape {self.shape}')
            # Could be optimized
            for s, e in self.normalized_intervals:
                if e > index:
                    return (index >= s) ^ self.inverse_mode
            return self.inverse_mode

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

        # This is numpy behavior
        if stop <= start:
            return np.zeros(0, dtype=np.bool)

        intervals = cy_intersection((start, stop), self.normalized_intervals)

        if self.inverse_mode:
            arr = np.ones(stop - start, dtype=np.bool)

            for i_start, i_end in intervals:
                arr[i_start - start:i_end - start] = False
        else:
            arr = np.zeros(stop - start, dtype=np.bool)

            for i_start, i_end in intervals:
                arr[i_start - start:i_end - start] = True

        return arr