Exemplo n.º 1
0
    def _plates_from_parent(self, index):

        plates = list(self.parents[index].plates)

        # Compute the plates. Note that Ellipsis has already been preprocessed
        # to a proper number of :
        k = 0
        for s in self.slices:
            # Then, each case separately: slice, newaxis, integer
            
            if isinstance(s, slice):
                # Slice, e.g., [2:5]
                N = slicelen(s)
                if N <= 0:
                    raise IndexError("Slicing leads to empty plates")
                plates[k] = N
                k += 1
                
            elif s is None:
                # [np.newaxis]
                plates = plates[:k] + [1] + plates[k:]
                k += 1
                
            elif misc.is_scalar_integer(s):
                # Integer, e.g., [3]
                del plates[k]
            else:
                raise RuntimeError("BUG: Unknown index type. Should capture earlier.")

        return tuple(plates)
Exemplo n.º 2
0
    def _plates_from_parent(self, index):

        plates = list(self.parents[index].plates)

        # Compute the plates. Note that Ellipsis has already been preprocessed
        # to a proper number of :
        k = 0
        for s in self.slices:
            # Then, each case separately: slice, newaxis, integer

            if isinstance(s, slice):
                # Slice, e.g., [2:5]
                N = slicelen(s)
                if N <= 0:
                    raise IndexError("Slicing leads to empty plates")
                plates[k] = N
                k += 1

            elif s is None:
                # [np.newaxis]
                plates = plates[:k] + [1] + plates[k:]
                k += 1

            elif misc.is_scalar_integer(s):
                # Integer, e.g., [3]
                del plates[k]
            else:
                raise RuntimeError(
                    "BUG: Unknown index type. Should capture earlier.")

        return tuple(plates)
Exemplo n.º 3
0
    def __init__(self, node, indices, plate_axis=-1, **kwargs):
        self._moments = node._moments
        self._parent_moments = (node._moments,)
        self._indices = np.array(indices)
        self._plate_axis = plate_axis
        self._original_length = node.plates[plate_axis]

        # Validate arguments
        if not misc.is_scalar_integer(plate_axis):
            raise ValueError("Plate axis must be integer")
        if plate_axis >= 0:
            raise ValueError("plate_axis must be negative index")
        if plate_axis < -len(node.plates):
            raise ValueError("plate_axis out of bounds")
        if not issubclass(self._indices.dtype.type, np.integer):
            raise ValueError("Indices must be integers")
        if (np.any(self._indices < -self._original_length) or
            np.any(self._indices >= self._original_length)):
            raise ValueError("Index out of bounds")

        super().__init__(node, dims=node.dims, **kwargs)
Exemplo n.º 4
0
    def __init__(self, node, indices, plate_axis=-1, **kwargs):
        self._moments = node._moments
        self._parent_moments = (node._moments, )
        self._indices = np.array(indices)
        self._plate_axis = plate_axis
        self._original_length = node.plates[plate_axis]

        # Validate arguments
        if not misc.is_scalar_integer(plate_axis):
            raise ValueError("Plate axis must be integer")
        if plate_axis >= 0:
            raise ValueError("plate_axis must be negative index")
        if plate_axis < -len(node.plates):
            raise ValueError("plate_axis out of bounds")
        if not issubclass(self._indices.dtype.type, np.integer):
            raise ValueError("Indices must be integers")
        if (np.any(self._indices < -self._original_length)
                or np.any(self._indices >= self._original_length)):
            raise ValueError("Index out of bounds")

        super().__init__(node, dims=node.dims, **kwargs)
Exemplo n.º 5
0
    def __init__(self, X, slices, **kwargs):

        self._moments = X._moments
        self._parent_moments = (X._moments,)

        # Force a list
        if not isinstance(slices, tuple):
            slices = [slices]
        else:
            slices = list(slices)

        #
        # Expand Ellipsis
        #

        # Compute the number of required axes and how Ellipsis is expanded
        num_axis = 0
        ellipsis_index = None
        for (k, s) in enumerate(slices):

            if misc.is_scalar_integer(s) or isinstance(s, slice):
                num_axis += 1

            elif s is None:
                pass
                
            elif s is Ellipsis:
                # Index is an ellipsis, e.g., [...]
                
                if ellipsis_index is None:
                    # Expand ...
                    ellipsis_index = k
                else:
                    # Interpret ... as :
                    num_axis += 1
                    slices[k] = slice(None)
                    
            else:
                raise TypeError("Invalid argument type: {0}".format(s.__class__))

        if num_axis > len(X.plates):
            raise IndexError("Too many indices")

        # The number of plates that were not given explicit slicing (either
        # Ellipsis was used or the number of slices was smaller than the number
        # of plate axes)
        expand_len = len(X.plates) - num_axis
        
        if ellipsis_index is not None:
            # Replace Ellipsis with correct number of :
            k = ellipsis_index
            del slices[k]
            slices = slices[:k] + [slice(None)] * expand_len + slices[k:]
        else:
            # Add trailing : so that each plate has explicit slicing
            slices = slices + [slice(None)] * expand_len

        #
        # Preprocess indexing:
        # - integer indices to non-negative values
        # - slice start/stop values to non-negative
        # - slice start/stop values based on the size of the plate
        #

        # Index for parent plates
        j = 0
        
        for (k, s) in enumerate(slices):

            if misc.is_scalar_integer(s):
                # Index is an integer, e.g., [3]
                
                if s < 0:
                    # Handle negative index
                    s += X.plates[j]
                if s < 0 or s >= X.plates[j]:
                    raise IndexError("Index out of range")
                # Store the preprocessed integer index
                slices[k] = s
                j += 1

            elif isinstance(s, slice):
                # Index is a slice, e.g., [2:6]
                
                # Normalize the slice
                s = slice(*(s.indices(X.plates[j])))
                if slicelen(s) <= 0:
                    raise IndexError("Slicing leads to empty plates")
                slices[k] = s
                j += 1

        self.slices = slices

        super().__init__(X,
                         dims=X.dims,
                         **kwargs)
Exemplo n.º 6
0
    def __reverse_indexing(slices, m_child, plates, dims):
        """
        A helpful function for performing reverse indexing/slicing
        """

        j = -1 # plate index for parent
        i = -1 # plate index for child
        child_slices = ()
        parent_slices = ()
        msg_plates = ()

        # Compute plate axes in the message from children
        ndim = len(dims)
        if ndim > 0:
            m_plates = np.shape(m_child)[:-ndim]
        else:
            m_plates = np.shape(m_child)

        for s in reversed(slices):

            if misc.is_scalar_integer(s):
                # Case: integer
                parent_slices = (s,) + parent_slices
                msg_plates = (plates[j],) + msg_plates
                j -= 1
            elif s is None:
                # Case: newaxis
                if -i <= len(m_plates):
                    child_slices = (0,) + child_slices
                i -= 1
            elif isinstance(s, slice):
                # Case: slice
                if -i <= len(m_plates):
                    child_slices = (slice(None),) + child_slices
                parent_slices = (s,) + parent_slices
                if ((-i > len(m_plates) or m_plates[i] == 1)
                    and slicelen(s) == plates[j]):
                    # Broadcasting can be applied. The message does not need
                    # to be explicitly shaped to the full size
                    msg_plates = (1,) + msg_plates
                else:
                    # No broadcasting. Must explicitly form the full size
                    # axis
                    msg_plates = (plates[j],) + msg_plates
                j -= 1
                i -= 1
            else:
                raise RuntimeError("BUG: Unknown index type. Should capture earlier.")

        # Set the elements of the message
        m_parent = np.zeros(msg_plates + dims)
        if np.ndim(m_parent) == 0 and np.ndim(m_child) == 0:
            m_parent = m_child
        elif np.ndim(m_parent) == 0:
            m_parent = m_child[child_slices]
        elif np.ndim(m_child) == 0:
            m_parent[parent_slices] = m_child
        else:
            m_parent[parent_slices] = m_child[child_slices]

        return m_parent
Exemplo n.º 7
0
    def __reverse_indexing(slices, m_child, plates, dims):
        """
        A helpful function for performing reverse indexing/slicing
        """

        j = -1  # plate index for parent
        i = -1  # plate index for child
        child_slices = ()
        parent_slices = ()
        msg_plates = ()

        # Compute plate axes in the message from children
        ndim = len(dims)
        if ndim > 0:
            m_plates = np.shape(m_child)[:-ndim]
        else:
            m_plates = np.shape(m_child)

        for s in reversed(slices):

            if misc.is_scalar_integer(s):
                # Case: integer
                parent_slices = (s, ) + parent_slices
                msg_plates = (plates[j], ) + msg_plates
                j -= 1
            elif s is None:
                # Case: newaxis
                if -i <= len(m_plates):
                    child_slices = (0, ) + child_slices
                i -= 1
            elif isinstance(s, slice):
                # Case: slice
                if -i <= len(m_plates):
                    child_slices = (slice(None), ) + child_slices
                parent_slices = (s, ) + parent_slices
                if ((-i > len(m_plates) or m_plates[i] == 1)
                        and slicelen(s) == plates[j]):
                    # Broadcasting can be applied. The message does not need
                    # to be explicitly shaped to the full size
                    msg_plates = (1, ) + msg_plates
                else:
                    # No broadcasting. Must explicitly form the full size
                    # axis
                    msg_plates = (plates[j], ) + msg_plates
                j -= 1
                i -= 1
            else:
                raise RuntimeError(
                    "BUG: Unknown index type. Should capture earlier.")

        # Set the elements of the message
        m_parent = np.zeros(msg_plates + dims)
        if np.ndim(m_parent) == 0 and np.ndim(m_child) == 0:
            m_parent = m_child
        elif np.ndim(m_parent) == 0:
            m_parent = m_child[child_slices]
        elif np.ndim(m_child) == 0:
            m_parent[parent_slices] = m_child
        else:
            m_parent[parent_slices] = m_child[child_slices]

        return m_parent
Exemplo n.º 8
0
    def __init__(self, X, slices, **kwargs):

        self._moments = X._moments
        self._parent_moments = (X._moments, )

        # Force a list
        if not isinstance(slices, tuple):
            slices = [slices]
        else:
            slices = list(slices)

        #
        # Expand Ellipsis
        #

        # Compute the number of required axes and how Ellipsis is expanded
        num_axis = 0
        ellipsis_index = None
        for (k, s) in enumerate(slices):

            if misc.is_scalar_integer(s) or isinstance(s, slice):
                num_axis += 1

            elif s is None:
                pass

            elif s is Ellipsis:
                # Index is an ellipsis, e.g., [...]

                if ellipsis_index is None:
                    # Expand ...
                    ellipsis_index = k
                else:
                    # Interpret ... as :
                    num_axis += 1
                    slices[k] = slice(None)

            else:
                raise TypeError("Invalid argument type: {0}".format(
                    s.__class__))

        if num_axis > len(X.plates):
            raise IndexError("Too many indices")

        # The number of plates that were not given explicit slicing (either
        # Ellipsis was used or the number of slices was smaller than the number
        # of plate axes)
        expand_len = len(X.plates) - num_axis

        if ellipsis_index is not None:
            # Replace Ellipsis with correct number of :
            k = ellipsis_index
            del slices[k]
            slices = slices[:k] + [slice(None)] * expand_len + slices[k:]
        else:
            # Add trailing : so that each plate has explicit slicing
            slices = slices + [slice(None)] * expand_len

        #
        # Preprocess indexing:
        # - integer indices to non-negative values
        # - slice start/stop values to non-negative
        # - slice start/stop values based on the size of the plate
        #

        # Index for parent plates
        j = 0

        for (k, s) in enumerate(slices):

            if misc.is_scalar_integer(s):
                # Index is an integer, e.g., [3]

                if s < 0:
                    # Handle negative index
                    s += X.plates[j]
                if s < 0 or s >= X.plates[j]:
                    raise IndexError("Index out of range")
                # Store the preprocessed integer index
                slices[k] = s
                j += 1

            elif isinstance(s, slice):
                # Index is a slice, e.g., [2:6]

                # Normalize the slice
                s = slice(*(s.indices(X.plates[j])))
                if slicelen(s) <= 0:
                    raise IndexError("Slicing leads to empty plates")
                slices[k] = s
                j += 1

        self.slices = slices

        super().__init__(X, dims=X.dims, **kwargs)