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)
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)
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)
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)
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)
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
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
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)