Advertisement
Guest User

Untitled

a guest
Jan 18th, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.04 KB | None | 0 0
  1. def rolling_window(array, window=(0,), asteps=None, wsteps=None, axes=None, toend=True):
  2. """Create a view of `array` which for every point gives the n-dimensional
  3. neighbourhood of size window. New dimensions are added at the end of
  4. `array` or after the corresponding original dimension.
  5.  
  6. Parameters
  7. ----------
  8. array : array_like
  9. Array to which the rolling window is applied.
  10. window : int or tuple
  11. Either a single integer to create a window of only the last axis or a
  12. tuple to create it for the last len(window) axes. 0 can be used as a
  13. to ignore a dimension in the window.
  14. asteps : tuple
  15. Aligned at the last axis, new steps for the original array, ie. for
  16. creation of non-overlapping windows. (Equivalent to slicing result)
  17. wsteps : int or tuple (same size as window)
  18. steps for the added window dimensions. These can be 0 to repeat values
  19. along the axis.
  20. axes: int or tuple
  21. If given, must have the same size as window. In this case window is
  22. interpreted as the size in the dimension given by axes. IE. a window
  23. of (2, 1) is equivalent to window=2 and axis=-2.
  24. toend : bool
  25. If False, the new dimensions are right after the corresponding original
  26. dimension, instead of at the end of the array. Adding the new axes at the
  27. end makes it easier to get the neighborhood, however toend=False will give
  28. a more intuitive result if you view the whole array.
  29.  
  30. Returns
  31. -------
  32. A view on `array` which is smaller to fit the windows and has windows added
  33. dimensions (0s not counting), ie. every point of `array` is an array of size
  34. window.
  35.  
  36. Examples
  37. --------
  38. >>> a = np.arange(9).reshape(3,3)
  39. >>> rolling_window(a, (2,2))
  40. array([[[[0, 1],
  41. [3, 4]],
  42.  
  43. [[1, 2],
  44. [4, 5]]],
  45.  
  46.  
  47. [[[3, 4],
  48. [6, 7]],
  49.  
  50. [[4, 5],
  51. [7, 8]]]])
  52.  
  53. Or to create non-overlapping windows, but only along the first dimension:
  54. >>> rolling_window(a, (2,0), asteps=(2,1))
  55. array([[[0, 3],
  56. [1, 4],
  57. [2, 5]]])
  58.  
  59. Note that the 0 is discared, so that the output dimension is 3:
  60. >>> rolling_window(a, (2,0), asteps=(2,1)).shape
  61. (1, 3, 2)
  62.  
  63. This is useful for example to calculate the maximum in all (overlapping)
  64. 2x2 submatrixes:
  65. >>> rolling_window(a, (2,2)).max((2,3))
  66. array([[4, 5],
  67. [7, 8]])
  68.  
  69. Or delay embedding (3D embedding with delay 2):
  70. >>> x = np.arange(10)
  71. >>> rolling_window(x, 3, wsteps=2)
  72. array([[0, 2, 4],
  73. [1, 3, 5],
  74. [2, 4, 6],
  75. [3, 5, 7],
  76. [4, 6, 8],
  77. [5, 7, 9]])
  78. """
  79. import numpy as np
  80. array = np.asarray(array)
  81. orig_shape = np.asarray(array.shape)
  82. window = np.atleast_1d(window).astype(int) # maybe crude to cast to int...
  83.  
  84. if axes is not None:
  85. axes = np.atleast_1d(axes)
  86. w = np.zeros(array.ndim, dtype=int)
  87. for axis, size in zip(axes, window):
  88. w[axis] = size
  89. window = w
  90.  
  91. # Check if window is legal:
  92. if window.ndim > 1:
  93. raise ValueError("`window` must be one-dimensional.")
  94. if np.any(window < 0):
  95. raise ValueError("All elements of `window` must be larger then 1.")
  96. if len(array.shape) < len(window):
  97. raise ValueError("`window` length must be less or equal `array` dimension.")
  98.  
  99. _asteps = np.ones_like(orig_shape)
  100. if asteps is not None:
  101. asteps = np.atleast_1d(asteps)
  102. if asteps.ndim != 1:
  103. raise ValueError("`asteps` must be either a scalar or one dimensional.")
  104. if len(asteps) > array.ndim:
  105. raise ValueError("`asteps` cannot be longer then the `array` dimension.")
  106. # does not enforce alignment, so that steps can be same as window too.
  107. _asteps[-len(asteps):] = asteps
  108.  
  109. if np.any(asteps < 1):
  110. raise ValueError("All elements of `asteps` must be larger then 1.")
  111. asteps = _asteps
  112.  
  113. _wsteps = np.ones_like(window)
  114. if wsteps is not None:
  115. wsteps = np.atleast_1d(wsteps)
  116. if wsteps.shape != window.shape:
  117. raise ValueError("`wsteps` must have the same shape as `window`.")
  118. if np.any(wsteps < 0):
  119. raise ValueError("All elements of `wsteps` must be larger then 0.")
  120.  
  121. _wsteps[:] = wsteps
  122. _wsteps[window == 0] = 1 # make sure that steps are 1 for non-existing dims.
  123. wsteps = _wsteps
  124.  
  125. # Check that the window would not be larger then the original:
  126. if np.any(orig_shape[-len(window):] < window * wsteps):
  127. raise ValueError("`window` * `wsteps` larger then `array` in at least one dimension.")
  128.  
  129. new_shape = orig_shape # just renaming...
  130.  
  131. # For calculating the new shape 0s must act like 1s:
  132. _window = window.copy()
  133. _window[_window==0] = 1
  134.  
  135. new_shape[-len(window):] += wsteps - _window * wsteps
  136. new_shape = (new_shape + asteps - 1) // asteps
  137. # make sure the new_shape is at least 1 in any "old" dimension (ie. steps
  138. # is (too) large, but we do not care.
  139. new_shape[new_shape < 1] = 1
  140. shape = new_shape
  141.  
  142. strides = np.asarray(array.strides)
  143. strides *= asteps
  144. new_strides = array.strides[-len(window):] * wsteps
  145.  
  146. # The full new shape and strides:
  147. if toend:
  148. new_shape = np.concatenate((shape, window))
  149. new_strides = np.concatenate((strides, new_strides))
  150. else:
  151. _ = np.zeros_like(shape)
  152. _[-len(window):] = window
  153. _window = _.copy()
  154. _[-len(window):] = new_strides
  155. _new_strides = _
  156.  
  157. new_shape = np.zeros(len(shape)*2, dtype=int)
  158. new_strides = np.zeros(len(shape)*2, dtype=int)
  159.  
  160. new_shape[::2] = shape
  161. new_strides[::2] = strides
  162. new_shape[1::2] = _window
  163. new_strides[1::2] = _new_strides
  164.  
  165. new_strides = new_strides[new_shape != 0]
  166. new_shape = new_shape[new_shape != 0]
  167.  
  168. return np.lib.stride_tricks.as_strided(array, shape=new_shape, strides=new_strides)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement