Repository: numpy/numpy

Issue:
Assigning values not working properly on arrays returned by meshgrid
On the current master branch, trying to assign a value to certain parts of an array returned by `meshgrid` isn't working properly:
```
import numpy as np
X = np.array([1.1, 2.2])
Y = np.array([3.3, 4.4])
x, y = np.meshgrid(X, Y)

print(x)
print(x[0, :])
x[0, :] = 0
print(x)
```
This prints
```
[[ 1.1  2.2]
 [ 1.1  2.2]]

[ 1.1  2.2]

[[ 0.  0.]
 [ 0.  0.]]
```
In this example only the top row of `x` should be set to zero, but the whole `x` array is set to zero. This is working correctly in version 1.1.12. This was discovered on https://github.com/matplotlib/matplotlib/issues/7686 and apparently was introduced by https://github.com/numpy/numpy/pull/5302


Discussion:
Looks like `0 in x.strides` is true here, and the caveats of `np.broadcast_arrays` apply. Except the documentation does not warn for that here, so this is a bug
But I would expect arrays returned by meshgrid to be accessed just like
normal arrays, which is what happens in the current released version of
numpy. Is this an intentional change that has been made to meshgrid for
1.1.13?

On 12 Feb 2017 2:35 a.m., "Eric Wieser" <notifications@github.com> wrote:

Looks like 0 in x.strides is true here, and the caveats of
np.broadcast_arrays apply. Except the documentation does not warn for that
here, so this is a bug

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<https://github.com/numpy/numpy/issues/8561#issuecomment-279192075>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AF6RfCXJNLEkJ0jUNb3Gw7k5Y_I307V9ks5rbm_ngaJpZM4L2pUf>
.

This behaviour changed in 3811083eee8d61548587f0d52286a08a7744d88f, possibly accidentally. @idfah?
I think this would be fixed simply by moving the `if copy_` lines below `np.broadcast`

Resolving patch:
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -4498,24 +4498,21 @@ def meshgrid(*xi, **kwargs):
             "Valid values for `indexing` are 'xy' and 'ij'.")
 
     s0 = (1,) * ndim
-    output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1::])
+    output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1:])
               for i, x in enumerate(xi)]
 
-    shape = [x.size for x in output]
-
     if indexing == 'xy' and ndim > 1:
         # switch first and second axis
-        output[0].shape = (1, -1) + (1,)*(ndim - 2)
-        output[1].shape = (-1, 1) + (1,)*(ndim - 2)
-        shape[0], shape[1] = shape[1], shape[0]
-
-    if copy_:
-        output = [x.copy() for x in output]
+        output[0].shape = (1, -1) + s0[2:]
+        output[1].shape = (-1, 1) + s0[2:]
 
-    if not sparse and len(output) > 0:
+    if not sparse:
         # Return the full N-D matrix (not only the 1-D vector)
         output = np.broadcast_arrays(*output, subok=True)
 
+    if copy_:
+        output = [x.copy() for x in output]
+
     return output
 
 
diff --git a/numpy/lib/stride_tricks.py b/numpy/lib/stride_tricks.py
--- a/numpy/lib/stride_tricks.py
+++ b/numpy/lib/stride_tricks.py
@@ -179,7 +179,7 @@ def _broadcast_shape(*args):
     supplied arrays against each other.
     """
     if not args:
-        raise ValueError('must provide at least one argument')
+        return ()
     # use the old-iterator because np.nditer does not handle size 0 arrays
     # consistently
     b = np.broadcast(*args[:32])


Test patch:
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -2266,6 +2266,16 @@ def test_return_type(self):
         assert_(X.dtype == x.dtype)
         assert_(Y.dtype == y.dtype)
 
+    def test_writeback(self):
+        # Issue 8561
+        X = np.array([1.1, 2.2])
+        Y = np.array([3.3, 4.4])
+        x, y = np.meshgrid(X, Y, sparse=False, copy=True)
+
+        x[0, :] = 0
+        assert_equal(x[0, :], 0)
+        assert_equal(x[1, :], X)
+
 
 class TestPiecewise(TestCase):
 
diff --git a/numpy/lib/tests/test_stride_tricks.py b/numpy/lib/tests/test_stride_tricks.py
--- a/numpy/lib/tests/test_stride_tricks.py
+++ b/numpy/lib/tests/test_stride_tricks.py
@@ -266,7 +266,7 @@ def test_broadcast_to_raises():
 
 def test_broadcast_shape():
     # broadcast_shape is already exercized indirectly by broadcast_arrays
-    assert_raises(ValueError, _broadcast_shape)
+    assert_equal(_broadcast_shape(), ())
     assert_equal(_broadcast_shape([1, 2]), (2,))
     assert_equal(_broadcast_shape(np.ones((1, 1))), (1, 1))
     assert_equal(_broadcast_shape(np.ones((1, 1)), np.ones((3, 4))), (3, 4))