Repository: SciTools/cartopy

Issue:
false masking of edge points (pcolormesh)
### Description

A pcolormesh of an array that contains NaN at the edge can mask (i.e. plot in white) some additional grid cells.


#### Code to reproduce

```python
import matplotlib
import cartopy
import matplotlib.pyplot as plt

import cartopy.crs as ccrs
import numpy as np

print(matplotlib.__version__)
print(cartopy.__version__)


lon = np.arange(-180, 180, 30)
lat = np.arange(75, -76, -30)
# lat = np.arange(90, -91, -30)

ones = np.ones(shape=lat.shape + lon.shape) * 1.0

f, axs = plt.subplots(
    1, 2, subplot_kw=dict(projection=ccrs.PlateCarree(central_longitude=15))
)

ax = axs[0]
ax.pcolormesh(lon, lat, ones, transform=ccrs.PlateCarree(), ec="0.3", lw=0.5)

ax = axs[1]

ones[0, :] = np.nan

ax.pcolormesh(lon, lat, ones, transform=ccrs.PlateCarree(), ec="0.3", lw=0.5)

for ax in axs:
    ax.coastlines()
    ax.set_global()
```

![cartopy](https://user-images.githubusercontent.com/10194086/132509306-ef98da0b-cf59-44d2-9c1e-c65ab8efea96.png)

You can play with the location of the NaNs - somtimes it works fine. Sometimes it leads to strange patterns. You can also uncomment the other lat coordinates and the pattern becomes even stranger.

<details>
 <summary>Full environment definition</summary>

<!-- fill in the following information as appropriate -->

### Operating system


### Cartopy version
matplotlib: 3.4.3
cartopy: 0.19.0.post1

### conda list

```
# packages in environment at /home/mathause/conda/envs/regionmask-docs:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       1_gnu    conda-forge
affine                    2.3.0                      py_0    conda-forge
aiohttp                   3.7.4.post0      py39h3811e60_0    conda-forge
alabaster                 0.7.12                     py_0    conda-forge
alsa-lib                  1.2.3                h516909a_0    conda-forge
appdirs                   1.4.4              pyh9f0ad1d_0    conda-forge
argon2-cffi               20.1.0           py39h3811e60_2    conda-forge
async-timeout             3.0.1                   py_1000    conda-forge
async_generator           1.10                       py_0    conda-forge
attrs                     21.2.0             pyhd8ed1ab_0    conda-forge
babel                     2.9.1              pyh44b312d_0    conda-forge
backcall                  0.2.0              pyh9f0ad1d_0    conda-forge
backports                 1.0                        py_2    conda-forge
backports.functools_lru_cache 1.6.4              pyhd8ed1ab_0    conda-forge
black                     21.8b0             pyhd8ed1ab_0    conda-forge
bleach                    4.1.0              pyhd8ed1ab_0    conda-forge
bokeh                     2.3.3            py39hf3d152e_0    conda-forge
boost-cpp                 1.74.0               hc6e9bd1_3    conda-forge
brotlipy                  0.7.0           py39h3811e60_1001    conda-forge
bzip2                     1.0.8                h7f98852_4    conda-forge
c-ares                    1.17.2               h7f98852_0    conda-forge
ca-certificates           2021.5.30            ha878542_0    conda-forge
cairo                     1.16.0            h6cf1ce9_1008    conda-forge
cartopy                   0.19.0.post1     py39h3b23250_1    conda-forge
certifi                   2021.5.30        py39hf3d152e_0    conda-forge
cffi                      1.14.6           py39he32792d_0    conda-forge
cfitsio                   3.470                hb418390_7    conda-forge
cftime                    1.5.0            py39hce5d2b2_0    conda-forge
chardet                   4.0.0            py39hf3d152e_1    conda-forge
charset-normalizer        2.0.0              pyhd8ed1ab_0    conda-forge
click                     7.1.2              pyh9f0ad1d_0    conda-forge
click-plugins             1.1.1                      py_0    conda-forge
cligj                     0.7.2              pyhd8ed1ab_0    conda-forge
cloudpickle               1.6.0                      py_0    conda-forge
colorama                  0.4.4              pyh9f0ad1d_0    conda-forge
cryptography              3.4.7            py39hbca0aa6_0    conda-forge
curl                      7.78.0               hea6ffbf_0    conda-forge
cycler                    0.10.0                     py_2    conda-forge
cytoolz                   0.11.0           py39h3811e60_3    conda-forge
dask                      2021.9.0           pyhd8ed1ab_0    conda-forge
dask-core                 2021.9.0           pyhd8ed1ab_0    conda-forge
dataclasses               0.8                pyhc8e2a94_3    conda-forge
dbus                      1.13.6               h48d8840_2    conda-forge
debugpy                   1.4.1            py39he80948d_0    conda-forge
decorator                 4.4.2                      py_0    conda-forge
defusedxml                0.7.1              pyhd8ed1ab_0    conda-forge
distributed               2021.9.0         py39hf3d152e_0    conda-forge
docutils                  0.16             py39hf3d152e_3    conda-forge
entrypoints               0.3             py39hde42818_1002    conda-forge
expat                     2.4.1                h9c3ff4c_0    conda-forge
fiona                     1.8.18           py39h494ca2c_1    conda-forge
fontconfig                2.13.1            hba837de_1005    conda-forge
freetype                  2.10.4               h0708190_1    conda-forge
freexl                    1.0.6                h7f98852_0    conda-forge
fsspec                    0.8.7              pyhd8ed1ab_0    conda-forge
gdal                      3.2.1            py39h409cc32_7    conda-forge
geopandas                 0.9.0              pyhd8ed1ab_1    conda-forge
geopandas-base            0.9.0              pyhd8ed1ab_1    conda-forge
geos                      3.9.1                h9c3ff4c_2    conda-forge
geotiff                   1.6.0                h2b14fbe_4    conda-forge
gettext                   0.19.8.1          h0b5b191_1005    conda-forge
giflib                    5.2.1                h36c2ea0_2    conda-forge
glib                      2.68.4               h9c3ff4c_0    conda-forge
glib-tools                2.68.4               h9c3ff4c_0    conda-forge
gst-plugins-base          1.18.4               hf529b03_2    conda-forge
gstreamer                 1.18.4               h76c114f_2    conda-forge
hdf4                      4.2.15               h10796ff_3    conda-forge
hdf5                      1.10.6          nompi_h6a2412b_1114    conda-forge
heapdict                  1.0.1                      py_0    conda-forge
icu                       68.1                 h58526e2_0    conda-forge
idna                      3.1                pyhd3deb0d_0    conda-forge
imagesize                 1.2.0                      py_0    conda-forge
importlib-metadata        4.8.1            py39hf3d152e_0    conda-forge
intake                    0.6.3              pyhd8ed1ab_0    conda-forge
intake-geopandas          0.3.0                    pypi_0    pypi
ipykernel                 6.3.1            py39hef51801_0    conda-forge
ipython                   7.27.0           py39hef51801_0    conda-forge
ipython_genutils          0.2.0                      py_1    conda-forge
ipywidgets                7.6.4              pyhd8ed1ab_0    conda-forge
jedi                      0.18.0           py39hf3d152e_2    conda-forge
jinja2                    3.0.1              pyhd8ed1ab_0    conda-forge
joblib                    1.0.1              pyhd8ed1ab_0    conda-forge
jpeg                      9d                   h36c2ea0_0    conda-forge
json-c                    0.15                 h98cffda_0    conda-forge
jsonschema                3.2.0              pyhd8ed1ab_3    conda-forge
jupyter                   1.0.0            py39hf3d152e_6    conda-forge
jupyter_client            7.0.2              pyhd8ed1ab_0    conda-forge
jupyter_console           6.4.0              pyhd8ed1ab_0    conda-forge
jupyter_core              4.7.1            py39hf3d152e_0    conda-forge
jupyterlab_pygments       0.1.2              pyh9f0ad1d_0    conda-forge
jupyterlab_widgets        1.0.1              pyhd8ed1ab_0    conda-forge
kealib                    1.4.14               hcc255d8_2    conda-forge
kiwisolver                1.3.2            py39h1a9c180_0    conda-forge
krb5                      1.19.2               hcc1bbae_0    conda-forge
lcms2                     2.12                 hddcbb42_0    conda-forge
ld_impl_linux-64          2.36.1               hea4e1c9_2    conda-forge
libblas                   3.9.0           11_linux64_openblas    conda-forge
libcblas                  3.9.0           11_linux64_openblas    conda-forge
libclang                  11.1.0          default_ha53f305_1    conda-forge
libcurl                   7.78.0               h2574ce0_0    conda-forge
libdap4                   3.20.6               hd7c4107_2    conda-forge
libedit                   3.1.20191231         he28a2e2_2    conda-forge
libev                     4.33                 h516909a_1    conda-forge
libevent                  2.1.10               hcdb4288_3    conda-forge
libffi                    3.3                  h58526e2_2    conda-forge
libgcc-ng                 11.1.0               hc902ee8_8    conda-forge
libgdal                   3.2.1                h38ff51b_7    conda-forge
libgfortran-ng            11.1.0               h69a702a_8    conda-forge
libgfortran5              11.1.0               h6c583b3_8    conda-forge
libglib                   2.68.4               h3e27bee_0    conda-forge
libgomp                   11.1.0               hc902ee8_8    conda-forge
libiconv                  1.16                 h516909a_0    conda-forge
libkml                    1.3.0             h238a007_1014    conda-forge
liblapack                 3.9.0           11_linux64_openblas    conda-forge
libllvm11                 11.1.0               hf817b99_2    conda-forge
libnetcdf                 4.7.4           nompi_h56d31a8_107    conda-forge
libnghttp2                1.43.0               h812cca2_0    conda-forge
libogg                    1.3.4                h7f98852_1    conda-forge
libopenblas               0.3.17          pthreads_h8fe5266_1    conda-forge
libopus                   1.3.1                h7f98852_1    conda-forge
libpng                    1.6.37               h21135ba_2    conda-forge
libpq                     13.3                 hd57d9b9_0    conda-forge
librttopo                 1.1.0                h1185371_6    conda-forge
libsodium                 1.0.18               h36c2ea0_1    conda-forge
libspatialindex           1.9.3                h9c3ff4c_4    conda-forge
libspatialite             5.0.1                he52d314_3    conda-forge
libssh2                   1.10.0               ha56f1ee_0    conda-forge
libstdcxx-ng              11.1.0               h56837e0_8    conda-forge
libtiff                   4.2.0                hbd63e13_2    conda-forge
libuuid                   2.32.1            h7f98852_1000    conda-forge
libvorbis                 1.3.7                h9c3ff4c_0    conda-forge
libwebp-base              1.2.1                h7f98852_0    conda-forge
libxcb                    1.13              h7f98852_1003    conda-forge
libxkbcommon              1.0.3                he3ba5ed_0    conda-forge
libxml2                   2.9.12               h72842e0_0    conda-forge
locket                    0.2.0                      py_2    conda-forge
lz4-c                     1.9.3                h9c3ff4c_1    conda-forge
mapclassify               2.4.3              pyhd8ed1ab_0    conda-forge
markupsafe                2.0.1            py39h3811e60_0    conda-forge
matplotlib-base           3.4.3            py39h2fa2bec_0    conda-forge
matplotlib-inline         0.1.2              pyhd8ed1ab_2    conda-forge
mistune                   0.8.4           py39h3811e60_1004    conda-forge
msgpack-python            1.0.2            py39h1a9c180_1    conda-forge
multidict                 5.1.0            py39h3811e60_1    conda-forge
munch                     2.5.0                      py_0    conda-forge
mypy_extensions           0.4.3            py39hf3d152e_3    conda-forge
mysql-common              8.0.25               ha770c72_0    conda-forge
mysql-libs                8.0.25               h935591d_0    conda-forge
nbclient                  0.5.4              pyhd8ed1ab_0    conda-forge
nbconvert                 6.1.0            py39hf3d152e_0    conda-forge
nbformat                  5.1.3              pyhd8ed1ab_0    conda-forge
ncurses                   6.2                  h58526e2_4    conda-forge
nest-asyncio              1.5.1              pyhd8ed1ab_0    conda-forge
netcdf4                   1.5.6           nompi_py39h36800e2_102    conda-forge
networkx                  2.6.2              pyhd8ed1ab_0    conda-forge
notebook                  6.4.3              pyha770c72_0    conda-forge
nspr                      4.30                 h9c3ff4c_0    conda-forge
nss                       3.69                 hb5efdd6_0    conda-forge
numpy                     1.21.2           py39hdbf815f_0    conda-forge
numpydoc                  1.1.0                      py_1    conda-forge
olefile                   0.46               pyh9f0ad1d_1    conda-forge
openjpeg                  2.4.0                hb52868f_1    conda-forge
openssl                   1.1.1l               h7f98852_0    conda-forge
packaging                 21.0               pyhd8ed1ab_0    conda-forge
pandas                    1.3.2            py39hde0f152_0    conda-forge
pandoc                    2.14.2               h7f98852_0    conda-forge
pandocfilters             1.4.2                      py_1    conda-forge
parso                     0.8.2              pyhd8ed1ab_0    conda-forge
partd                     1.2.0              pyhd8ed1ab_0    conda-forge
pathspec                  0.9.0              pyhd8ed1ab_0    conda-forge
pcre                      8.45                 h9c3ff4c_0    conda-forge
pexpect                   4.8.0              pyh9f0ad1d_2    conda-forge
pickleshare               0.7.5           py39hde42818_1002    conda-forge
pillow                    8.2.0            py39hf95b381_1    conda-forge
pip                       21.2.4             pyhd8ed1ab_0    conda-forge
pixman                    0.40.0               h36c2ea0_0    conda-forge
platformdirs              2.3.0              pyhd8ed1ab_0    conda-forge
pooch                     1.5.1              pyhd8ed1ab_0    conda-forge
poppler                   0.89.0               h2de54a5_5    conda-forge
poppler-data              0.4.10                        0    conda-forge
postgresql                13.3                 h2510834_0    conda-forge
proj                      7.2.0                h277dcde_2    conda-forge
prometheus_client         0.11.0             pyhd8ed1ab_0    conda-forge
prompt-toolkit            3.0.20             pyha770c72_0    conda-forge
prompt_toolkit            3.0.20               hd8ed1ab_0    conda-forge
psutil                    5.8.0            py39h3811e60_1    conda-forge
pthread-stubs             0.4               h36c2ea0_1001    conda-forge
ptyprocess                0.7.0              pyhd3deb0d_0    conda-forge
pycparser                 2.20               pyh9f0ad1d_2    conda-forge
pygeos                    0.10.2           py39ha61afbd_0    conda-forge
pygments                  2.10.0             pyhd8ed1ab_0    conda-forge
pyopenssl                 20.0.1             pyhd8ed1ab_0    conda-forge
pyparsing                 2.4.7              pyh9f0ad1d_0    conda-forge
pyproj                    3.1.0            py39h50a64a9_3    conda-forge
pyqt                      5.12.3           py39hf3d152e_7    conda-forge
pyqt-impl                 5.12.3           py39h0fcd23e_7    conda-forge
pyqt5-sip                 4.19.18          py39he80948d_7    conda-forge
pyqtchart                 5.12             py39h0fcd23e_7    conda-forge
pyqtwebengine             5.12.1           py39h0fcd23e_7    conda-forge
pyrsistent                0.17.3           py39h3811e60_2    conda-forge
pyshp                     2.1.3              pyh44b312d_0    conda-forge
pysocks                   1.7.1            py39hf3d152e_3    conda-forge
python                    3.9.7           h49503c6_0_cpython    conda-forge
python-dateutil           2.8.2              pyhd8ed1ab_0    conda-forge
python_abi                3.9                      2_cp39    conda-forge
pytz                      2021.1             pyhd8ed1ab_0    conda-forge
pyyaml                    5.4.1            py39h3811e60_1    conda-forge
pyzmq                     22.2.1           py39h37b5a0c_0    conda-forge
qt                        5.12.9               hda022c4_4    conda-forge
qtconsole                 5.1.1              pyhd8ed1ab_0    conda-forge
qtpy                      1.11.0             pyhd8ed1ab_0    conda-forge
rasterio                  1.2.6            py39h63973eb_0    conda-forge
readline                  8.1                  h46c0cb4_0    conda-forge
regex                     2021.8.28        py39h3811e60_0    conda-forge
regionmask                0.7.1.dev18+g0dc6632.d20210906           dev_0    <develop>
requests                  2.26.0             pyhd8ed1ab_0    conda-forge
rtree                     0.9.7            py39hb102c33_2    conda-forge
scikit-learn              0.24.2           py39h7c5d8c9_1    conda-forge
scipy                     1.7.1            py39hee8e79c_0    conda-forge
send2trash                1.8.0              pyhd8ed1ab_0    conda-forge
setuptools                57.4.0           py39hf3d152e_0    conda-forge
shapely                   1.7.1            py39ha61afbd_5    conda-forge
six                       1.16.0             pyh6c4a22f_0    conda-forge
snowballstemmer           2.1.0              pyhd8ed1ab_0    conda-forge
snuggs                    1.4.7                      py_0    conda-forge
sortedcontainers          2.4.0              pyhd8ed1ab_0    conda-forge
sphinx                    4.1.2              pyh6c4a22f_1    conda-forge
sphinx_rtd_theme          0.5.2              pyhd8ed1ab_1    conda-forge
sphinxcontrib-applehelp   1.0.2                      py_0    conda-forge
sphinxcontrib-devhelp     1.0.2                      py_0    conda-forge
sphinxcontrib-htmlhelp    2.0.0              pyhd8ed1ab_0    conda-forge
sphinxcontrib-jsmath      1.0.1                      py_0    conda-forge
sphinxcontrib-qthelp      1.0.3                      py_0    conda-forge
sphinxcontrib-serializinghtml 1.1.5              pyhd8ed1ab_0    conda-forge
sqlite                    3.36.0               h9cd32fc_0    conda-forge
tblib                     1.7.0              pyhd8ed1ab_0    conda-forge
terminado                 0.11.1           py39hf3d152e_0    conda-forge
testpath                  0.5.0              pyhd8ed1ab_0    conda-forge
threadpoolctl             2.2.0              pyh8a188c0_0    conda-forge
tiledb                    2.2.9                h91fcb0e_0    conda-forge
tk                        8.6.11               h27826a3_1    conda-forge
tomli                     1.2.1              pyhd8ed1ab_0    conda-forge
toolz                     0.11.1                     py_0    conda-forge
tornado                   6.1              py39h3811e60_1    conda-forge
traitlets                 5.1.0              pyhd8ed1ab_0    conda-forge
typed-ast                 1.4.3            py39h3811e60_0    conda-forge
typing-extensions         3.10.0.0             hd8ed1ab_0    conda-forge
typing_extensions         3.10.0.0           pyha770c72_0    conda-forge
tzcode                    2021a                h7f98852_2    conda-forge
tzdata                    2021a                he74cb21_1    conda-forge
urllib3                   1.26.6             pyhd8ed1ab_0    conda-forge
wcwidth                   0.2.5              pyh9f0ad1d_2    conda-forge
webencodings              0.5.1                      py_1    conda-forge
wheel                     0.37.0             pyhd8ed1ab_1    conda-forge
widgetsnbextension        3.5.1            py39hf3d152e_4    conda-forge
xarray                    0.19.0             pyhd8ed1ab_1    conda-forge
xerces-c                  3.2.3                h9d8b166_2    conda-forge
xorg-kbproto              1.0.7             h7f98852_1002    conda-forge
xorg-libice               1.0.10               h7f98852_0    conda-forge
xorg-libsm                1.2.3             hd9c2040_1000    conda-forge
xorg-libx11               1.7.2                h7f98852_0    conda-forge
xorg-libxau               1.0.9                h7f98852_0    conda-forge
xorg-libxdmcp             1.1.3                h7f98852_0    conda-forge
xorg-libxext              1.3.4                h7f98852_1    conda-forge
xorg-libxrender           0.9.10            h7f98852_1003    conda-forge
xorg-renderproto          0.11.1            h7f98852_1002    conda-forge
xorg-xextproto            7.3.0             h7f98852_1002    conda-forge
xorg-xproto               7.0.31            h7f98852_1007    conda-forge
xz                        5.2.5                h516909a_1    conda-forge
yaml                      0.2.5                h516909a_0    conda-forge
yarl                      1.6.3            py39h3811e60_2    conda-forge
zeromq                    4.3.4                h9c3ff4c_1    conda-forge
zict                      2.0.0                      py_0    conda-forge
zipp                      3.5.0              pyhd8ed1ab_0    conda-forge
zlib                      1.2.11            h516909a_1010    conda-forge
zstd                      1.4.9                ha95c52a_0    conda-forge
```

### pip list

```
```

</details>



Discussion:

Resolving patch:
diff --git a/lib/cartopy/mpl/geoaxes.py b/lib/cartopy/mpl/geoaxes.py
--- a/lib/cartopy/mpl/geoaxes.py
+++ b/lib/cartopy/mpl/geoaxes.py
@@ -1880,10 +1880,8 @@ def _pcolormesh_patched(self, *args, **kwargs):
                     C_mask = getattr(C, 'mask', None)
 
                     # create the masked array to be used with this pcolormesh
-                    if C_mask is not None:
-                        pcolormesh_data = np.ma.array(C, mask=mask | C_mask)
-                    else:
-                        pcolormesh_data = np.ma.array(C, mask=mask)
+                    full_mask = mask if C_mask is None else mask | C_mask
+                    pcolormesh_data = np.ma.array(C, mask=full_mask)
 
                     collection.set_array(pcolormesh_data.ravel())
 
@@ -1901,16 +1899,22 @@ def _pcolormesh_patched(self, *args, **kwargs):
                         # We will add the original data mask in later to
                         # make sure that set_array can work in future
                         # calls on the proper sized array inputs.
-                        pcolor_data = np.ma.array(C.data, mask=~mask)
+                        # NOTE: we don't use C.data here because C.data could
+                        #       contain nan's which would be masked in the
+                        #       pcolor routines, which we don't want. We will
+                        #       fill in the proper data later with set_array()
+                        #       calls.
+                        pcolor_data = np.ma.array(np.zeros(C.shape),
+                                                  mask=~mask)
                         pcolor_col = self.pcolor(pts[..., 0], pts[..., 1],
                                                  pcolor_data, zorder=zorder,
                                                  **kwargs)
                         # Now add back in the masked data if there was any
-                        if C_mask is not None:
-                            pcolor_data = np.ma.array(C, mask=~mask | C_mask)
-                            # The pcolor_col is now possibly shorter than the
-                            # actual collection, so grab the masked cells
-                            pcolor_col.set_array(pcolor_data[mask].ravel())
+                        full_mask = ~mask if C_mask is None else ~mask | C_mask
+                        pcolor_data = np.ma.array(C, mask=full_mask)
+                        # The pcolor_col is now possibly shorter than the
+                        # actual collection, so grab the masked cells
+                        pcolor_col.set_array(pcolor_data[mask].ravel())
                         pcolor_col.set_cmap(cmap)
                         pcolor_col.set_norm(norm)
                         pcolor_col.set_clim(vmin, vmax)


Test patch:
diff --git a/lib/cartopy/tests/mpl/test_mpl_integration.py b/lib/cartopy/tests/mpl/test_mpl_integration.py
--- a/lib/cartopy/tests/mpl/test_mpl_integration.py
+++ b/lib/cartopy/tests/mpl/test_mpl_integration.py
@@ -605,6 +605,19 @@ def test_pcolormesh_diagonal_wrap():
     assert hasattr(mesh, "_wrapped_collection_fix")
 
 
+def test_pcolormesh_nan_wrap():
+    # Check that data with nan's as input still creates
+    # the proper number of pcolor cells and those aren't
+    # masked in the process.
+    xs, ys = np.meshgrid([120, 160, 200], [-30, 0, 30])
+    data = np.ones((2, 2)) * np.nan
+
+    ax = plt.axes(projection=ccrs.PlateCarree())
+    mesh = ax.pcolormesh(xs, ys, data)
+    pcolor = getattr(mesh, "_wrapped_collection_fix")
+    assert len(pcolor.get_paths()) == 2
+
+
 @pytest.mark.natural_earth
 @ImageTesting(['pcolormesh_goode_wrap'])
 def test_pcolormesh_goode_wrap():