Repository: matplotlib/matplotlib
Pull request: MNT: Check the input sizes of regular X,Y in pcolorfast
Closes #28059.

^

Problem statement:
[Bug]: pcolorfast should validate that regularly spaced X or Y inputs have the right size
### Bug summary

Currently, when X/Y are passed to pcolorfast and are regularly spaced arrays, pcolorfast just uses their first and last values for the image extents, without verifying that the coordinate sizes are actually correct.

### Code for reproduction

```Python
from pylab import *
gca().pcolorfast(arange(5), arange(13), np.random.rand(20, 20))  # or whatever sizes
```


### Actual outcome

no error

### Expected outcome

a validation error

### Additional information

_No response_

### Operating system

any

### Matplotlib Version

3.9.0.dev1479+g8d3dfce637

### Matplotlib Backend

any

### Python version

3012

### Jupyter version

no

### Installation

git checkout

Hints from issue discussion:
Apologies if I am misunderstanding the problem. When you say verifying that the coordinate sizes are actually correct, can you elaborate a bit more?

I understand that you mean this issue occurs if you have two regularly spaced arrays for X and Y, such as X = [1, 2, 3, 4] and Y=[2, 4, 6, 8, 10]. When those are used for example, the coordinate sizes should look like what? Do you mean the spacing of the values on each axis?

Commit message: MNT: Check the input sizes of regular X,Y in pcolorfast

Closes #28059.

Patch to review:
diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py
index d7b649ae437f..6824006e7bdf 100644
--- a/lib/matplotlib/axes/_axes.py
+++ b/lib/matplotlib/axes/_axes.py
@@ -6634,6 +6634,15 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
                 if x.size == 2 and y.size == 2:
                     style = "image"
                 else:
+                    if x.size != nc + 1:
+                        raise ValueError(
+                            f"Length of X ({x.size}) must be one larger than the "
+                            f"number of columns in C ({nc})")
+                    if y.size != nr + 1:
+                        raise ValueError(
+                            f"Length of Y ({y.size}) must be one larger than the "
+                            f"number of rows in C ({nr})"
+                        )
                     dx = np.diff(x)
                     dy = np.diff(y)
                     if (np.ptp(dx) < 0.01 * abs(dx.mean()) and
diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index 33c81c44abaf..2ee2339405c8 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -6626,6 +6626,27 @@ def test_pcolorfast_bad_dims():
         ax.pcolorfast(np.empty(6), np.empty((4, 7)), np.empty((8, 8)))
 
 
+def test_pcolorfast_regular_xy_incompatible_size():
+    """
+    Test that the sizes of X, Y, C are compatible for regularly spaced X, Y.
+
+    Note that after the regualar-spacing check, pcolorfast may go into the
+    fast "image" mode, where the individual X, Y positions are not used anymore.
+    Therefore, the algorithm had worked with any regularly number of regularly
+    spaced values, but discarded their values.
+    """
+    fig, ax = plt.subplots()
+    with pytest.raises(
+            ValueError, match="Length of X (5) must be one larger than the "
+                              "number of columns in C (20)"):
+        ax.pcolorfast(np.arange(5), np.arange(11), np.random.rand(10, 20))
+
+    with pytest.raises(
+        ValueError, match="Length of Y (5) must be one larger than the "
+                          "number rows in C (10)"):
+        ax.pcolorfast(np.arange(21), np.arange(5), np.random.rand(10, 20))
+
+
 def test_shared_scale():
     fig, axs = plt.subplots(2, 2, sharex=True, sharey=True)
 


Code review comments:
diff_hunk: @@ -6626,6 +6626,27 @@ def test_pcolorfast_bad_dims():
         ax.pcolorfast(np.empty(6), np.empty((4, 7)), np.empty((8, 8)))
 
 
+def test_pcolorfast_regular_xy_incompatible_size():
+    """
+    Test that the sizes of X, Y, C are compatible for regularly spaced X, Y.
+
+    Note that after the regualar-spacing check, pcolorfast may go into the
+    fast "image" mode, where the individual X, Y positions are not used anymore.
+    Therefore, the algorithm had worked with any regularly number of regularly
+    spaced values, but discarded their values.
+    """
+    fig, ax = plt.subplots()
+    with pytest.raises(
+            ValueError, match="Length of X (5) must be one larger than the "
+                              "number of columns in C (20)"):
path: lib/matplotlib/tests/test_axes.py
text: @user1:
```suggestion
            ValueError, match=r"Length of X \(5\) must be one larger than the "
                              r"number of columns in C \(20\)"):
```

diff_hunk: @@ -6626,6 +6626,27 @@ def test_pcolorfast_bad_dims():
         ax.pcolorfast(np.empty(6), np.empty((4, 7)), np.empty((8, 8)))
 
 
+def test_pcolorfast_regular_xy_incompatible_size():
+    """
+    Test that the sizes of X, Y, C are compatible for regularly spaced X, Y.
+
+    Note that after the regualar-spacing check, pcolorfast may go into the
+    fast "image" mode, where the individual X, Y positions are not used anymore.
+    Therefore, the algorithm had worked with any regularly number of regularly
+    spaced values, but discarded their values.
+    """
+    fig, ax = plt.subplots()
+    with pytest.raises(
+            ValueError, match="Length of X (5) must be one larger than the "
+                              "number of columns in C (20)"):
+        ax.pcolorfast(np.arange(5), np.arange(11), np.random.rand(10, 20))
+
+    with pytest.raises(
+        ValueError, match="Length of Y (5) must be one larger than the "
+                          "number rows in C (10)"):
path: lib/matplotlib/tests/test_axes.py
text: @user1:
```suggestion
            ValueError, match=r"Length of Y \(5\) must be one larger than the "
                              r"number of rows in C \(10\)"):
```