diff options
Diffstat (limited to 'numpy/lib')
-rw-r--r-- | numpy/lib/function_base.py | 50 | ||||
-rw-r--r-- | numpy/lib/shape_base.py | 2 | ||||
-rw-r--r-- | numpy/lib/tests/test__version.py | 13 | ||||
-rw-r--r-- | numpy/lib/tests/test_function_base.py | 43 | ||||
-rw-r--r-- | numpy/lib/tests/test_shape_base.py | 9 |
5 files changed, 101 insertions, 16 deletions
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 820168663..007ff42a4 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1122,19 +1122,28 @@ def gradient(f, *varargs, **kwargs): ---------- f : array_like An N-dimensional array containing samples of a scalar function. - varargs : list of scalar, optional + varargs : scalar or list of scalar, optional N scalars specifying the sample distances for each dimension, i.e. `dx`, `dy`, `dz`, ... Default distance: 1. + single scalar specifies sample distance for all dimensions. + if `axis` is given, the number of varargs must equal the number of axes. edge_order : {1, 2}, optional Gradient is calculated using N\ :sup:`th` order accurate differences at the boundaries. Default: 1. .. versionadded:: 1.9.1 + axis : None or int or tuple of ints, optional + Gradient is calculated only along the given axis or axes + The default (axis = None) is to calculate the gradient for all the axes of the input array. + axis may be negative, in which case it counts from the last to the first axis. + + .. versionadded:: 1.11.0 + Returns ------- gradient : list of ndarray - Each element of `list` has the same shape as `f` giving the derivative + Each element of `list` has the same shape as `f` giving the derivative of `f` with respect to each dimension. Examples @@ -1145,10 +1154,10 @@ def gradient(f, *varargs, **kwargs): >>> np.gradient(x, 2) array([ 0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ]) - For two dimensional arrays, the return will be two arrays ordered by - axis. In this example the first array stands for the gradient in + For two dimensional arrays, the return will be two arrays ordered by + axis. In this example the first array stands for the gradient in rows and the second one in columns direction: - + >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float)) [array([[ 2., 2., -1.], [ 2., 2., -1.]]), array([[ 1. , 2.5, 4. ], @@ -1159,15 +1168,38 @@ def gradient(f, *varargs, **kwargs): >>> y = x**2 >>> np.gradient(y, dx, edge_order=2) array([-0., 2., 4., 6., 8.]) + + The axis keyword can be used to specify a subset of axes of which the gradient is calculated + >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float), axis=0) + array([[ 2., 2., -1.], + [ 2., 2., -1.]]) """ f = np.asanyarray(f) N = len(f.shape) # number of dimensions + + axes = kwargs.pop('axis', None) + if axes is None: + axes = tuple(range(N)) + # check axes to have correct type and no duplicate entries + if isinstance(axes, int): + axes = (axes,) + if not isinstance(axes, tuple): + raise TypeError("A tuple of integers or a single integer is required") + + # normalize axis values: + axes = tuple(x + N if x < 0 else x for x in axes) + if max(axes) >= N or min(axes) < 0: + raise ValueError("'axis' entry is out of bounds") + + if len(set(axes)) != len(axes): + raise ValueError("duplicate value in 'axis'") + n = len(varargs) if n == 0: dx = [1.0]*N elif n == 1: dx = [varargs[0]]*N - elif n == N: + elif n == len(axes): dx = list(varargs) else: raise SyntaxError( @@ -1211,7 +1243,7 @@ def gradient(f, *varargs, **kwargs): else: y = f - for axis in range(N): + for i, axis in enumerate(axes): if y.shape[axis] < 2: raise ValueError( @@ -1267,7 +1299,7 @@ def gradient(f, *varargs, **kwargs): out[slice1] = (3.0*y[slice2] - 4.0*y[slice3] + y[slice4])/2.0 # divide by step size - out /= dx[axis] + out /= dx[i] outvals.append(out) # reset the slice object in this dimension to ":" @@ -1276,7 +1308,7 @@ def gradient(f, *varargs, **kwargs): slice3[axis] = slice(None) slice4[axis] = slice(None) - if N == 1: + if len(axes) == 1: return outvals[0] else: return outvals diff --git a/numpy/lib/shape_base.py b/numpy/lib/shape_base.py index 26c2aab04..b2beef0a8 100644 --- a/numpy/lib/shape_base.py +++ b/numpy/lib/shape_base.py @@ -424,7 +424,7 @@ def array_split(ary, indices_or_sections, axis=0): # This "kludge" was introduced here to replace arrays shaped (0, 10) # or similar with an array shaped (0,). # There seems no need for this, so give a FutureWarning to remove later. - if sub_arys[-1].size == 0 and sub_arys[-1].ndim != 1: + if any(arr.size == 0 and arr.ndim != 1 for arr in sub_arys): warnings.warn("in the future np.array_split will retain the shape of " "arrays with a zero size, instead of replacing them by " "`array([])`, which always has a shape of (0,).", diff --git a/numpy/lib/tests/test__version.py b/numpy/lib/tests/test__version.py index bbafe68eb..993c9d507 100644 --- a/numpy/lib/tests/test__version.py +++ b/numpy/lib/tests/test__version.py @@ -48,6 +48,19 @@ def test_dev_a_b_rc_mixed(): assert_(NumpyVersion('1.9.0a2.dev-6acvda54') < '1.9.0a2') +def test_dev0_version(): + assert_(NumpyVersion('1.9.0.dev0+Unknown') < '1.9.0') + for ver in ['1.9.0', '1.9.0a1', '1.9.0b2', '1.9.0b2.dev0+ffffffff']: + assert_(NumpyVersion('1.9.0.dev0+f16acvda') < ver) + + assert_(NumpyVersion('1.9.0.dev0+f16acvda') == '1.9.0.dev0+11111111') + + +def test_dev0_a_b_rc_mixed(): + assert_(NumpyVersion('1.9.0a2.dev0+f16acvda') == '1.9.0a2.dev0+11111111') + assert_(NumpyVersion('1.9.0a2.dev0+6acvda54') < '1.9.0a2') + + def test_raises(): for ver in ['1.9', '1,9.0', '1.7.x']: assert_raises(ValueError, NumpyVersion, ver) diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index af9315d83..5e758fb89 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -601,6 +601,31 @@ class TestGradient(TestCase): num_error = np.abs((np.gradient(y, dx, edge_order=2) / analytical) - 1) assert_(np.all(num_error < 0.03) == True) + def test_specific_axes(self): + # Testing that gradient can work on a given axis only + v = [[1, 1], [3, 4]] + x = np.array(v) + dx = [np.array([[2., 3.], [2., 3.]]), + np.array([[0., 0.], [1., 1.]])] + assert_array_equal(gradient(x, axis=0), dx[0]) + assert_array_equal(gradient(x, axis=1), dx[1]) + assert_array_equal(gradient(x, axis=-1), dx[1]) + assert_array_equal(gradient(x, axis=(1,0)), [dx[1], dx[0]]) + + # test axis=None which means all axes + assert_almost_equal(gradient(x, axis=None), [dx[0], dx[1]]) + # and is the same as no axis keyword given + assert_almost_equal(gradient(x, axis=None), gradient(x)) + + # test vararg order + assert_array_equal(gradient(x, 2, 3, axis=(1,0)), [dx[1]/2.0, dx[0]/3.0]) + # test maximal number of varargs + assert_raises(SyntaxError, gradient, x, 1, 2, axis=1) + + assert_raises(ValueError, gradient, x, axis=3) + assert_raises(ValueError, gradient, x, axis=-3) + assert_raises(TypeError, gradient, x, axis=[1,]) + class TestAngle(TestCase): @@ -1888,19 +1913,25 @@ class TestBincount(TestCase): def test_with_incorrect_minlength(self): x = np.array([], dtype=int) - assert_raises_regex(TypeError, "an integer is required", + assert_raises_regex(TypeError, + "'str' object cannot be interpreted", lambda: np.bincount(x, minlength="foobar")) - assert_raises_regex(ValueError, "must be positive", + assert_raises_regex(ValueError, + "must be positive", lambda: np.bincount(x, minlength=-1)) - assert_raises_regex(ValueError, "must be positive", + assert_raises_regex(ValueError, + "must be positive", lambda: np.bincount(x, minlength=0)) x = np.arange(5) - assert_raises_regex(TypeError, "an integer is required", + assert_raises_regex(TypeError, + "'str' object cannot be interpreted", lambda: np.bincount(x, minlength="foobar")) - assert_raises_regex(ValueError, "minlength must be positive", + assert_raises_regex(ValueError, + "minlength must be positive", lambda: np.bincount(x, minlength=-1)) - assert_raises_regex(ValueError, "minlength must be positive", + assert_raises_regex(ValueError, + "minlength must be positive", lambda: np.bincount(x, minlength=0)) diff --git a/numpy/lib/tests/test_shape_base.py b/numpy/lib/tests/test_shape_base.py index 3f2d8d5b4..8ab72b9f9 100644 --- a/numpy/lib/tests/test_shape_base.py +++ b/numpy/lib/tests/test_shape_base.py @@ -111,6 +111,15 @@ class TestArraySplit(TestCase): compare_results(res, desired) assert_(a.dtype.type is res[-1].dtype.type) + # Same thing for manual splits: + res = assert_warns(FutureWarning, array_split, a, [0, 1, 2], axis=0) + + # After removing the FutureWarning, the last should be zeros((0, 10)) + desired = [np.array([]), np.array([np.arange(10)]), + np.array([np.arange(10)])] + compare_results(res, desired) + assert_(a.dtype.type is res[-1].dtype.type) + def test_integer_split_2D_cols(self): a = np.array([np.arange(10), np.arange(10)]) res = array_split(a, 3, axis=-1) |