SciTools / cartopy

Cartopy - a cartographic python library with matplotlib support
https://scitools.org.uk/cartopy/docs/latest
BSD 3-Clause "New" or "Revised" License
1.43k stars 364 forks source link

Lines don't appear when plotting with >1000 points #1442

Closed dantonacci closed 4 years ago

dantonacci commented 4 years ago

Description

ax.plot stops showing the line on the axis if there are more than 1000 lat/lon points on a Mercator projection (haven't tried others). The problem doesn't occur if the longitude crosses 0 or I manually transform the points before plotting them.

It might be related to #1240 and #1246, though in this case, lines are desired, not just markers.

Code to reproduce

An example of the problem. Going from 1000 points to 1001 points suddenly prevents the line from showing up.

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(1, 2, subplot_kw={'projection': ccrs.Mercator()})
for ax, num_points in zip(axes, [1000, 1001]):
    lats = np.linspace(35, 37, num_points)
    lons = np.linspace(-117, -115, num_points)
    ax.plot(lons, lats, transform=ccrs.PlateCarree())
    ax.set_title(f'Number of lat/lon points: {num_points}')

num_points_bad

Manually transforming the points prior to plotting fixes the problem.

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(1, 2, subplot_kw={'projection': ccrs.Mercator()})
for ax, num_points in zip(axes, [1000, 1001]):
    lats = np.linspace(35, 37, num_points)
    lons = np.linspace(-117, -115, num_points)
    points = ax.projection.transform_points(ccrs.PlateCarree(), lons, lats)
    lines2 = ax.plot(points[:, 0], points[:, 1])
    ax.set_title(f'Number of lat/lon points: {num_points}')

num_points_good

Traceback

Full environment definition ### Operating system Windows 10 Matplotlib backend: Qt5Agg ### Cartopy version Cartopy 0.17.0 (conda py36h5ae9855_1) ### conda list ``` # packages in environment at C:\anaconda3\envs\pyprop: # # Name Version Build Channel alabaster 0.7.12 py36_0 altgraph 0.16.1 py_0 apipkg 1.5 py36_0 asn1crypto 1.2.0 py36_0 aspy.yaml 1.3.0 py_0 conda-forge astroid 2.3.3 py36_0 atomicwrites 1.3.0 py36_1 attrs 19.3.0 py_0 autopep8 1.4.4 py_0 babel 2.8.0 py_0 backcall 0.1.0 py36_0 blas 1.0 mkl ca-certificates 2019.11.27 0 cached-property 1.5.1 py_1 cartopy 0.17.0 py36h5ae9855_1 certifi 2019.11.28 py36_0 cffi 1.13.2 py36h7a1dbc1_0 cfgv 2.0.1 py_0 conda-forge chardet 3.0.4 py36_1003 cloudpickle 1.2.2 py_0 colorama 0.4.3 py_0 construct 2.9.45 py_0 conda-forge coverage 5.0 py36he774522_0 cryptography 2.8 py36h7a1dbc1_0 cycler 0.10.0 py36h009560c_0 cython 0.29.14 py36ha925a31_0 decorator 4.4.1 py_0 docutils 0.15.2 py36_0 editdistance 0.5.3 py36h6538335_0 conda-forge entrypoints 0.3 py36_0 execnet 1.7.1 py_0 flake8 3.7.9 py36_0 freetype 2.9.1 ha9979f8_1 future 0.18.2 py36_0 geos 3.7.1 h33f27b4_0 icc_rt 2019.0.0 h0cc432a_1 icu 58.2 ha66f8fd_1 identify 1.4.9 py_0 conda-forge idna 2.8 py36_0 imagesize 1.2.0 py_0 importlib_metadata 1.3.0 py36_0 importlib_resources 1.0.2 py36_1000 conda-forge intel-openmp 2019.4 245 ipykernel 5.1.3 py36h39e3cac_0 ipython 7.11.1 py36h39e3cac_0 ipython_genutils 0.2.0 py36_0 isort 4.3.21 py36_0 jedi 0.15.2 py36_0 jinja2 2.10.3 py_0 joblib 0.14.1 py_0 jpeg 9b hb83a4c4_2 jupyter_client 5.3.4 py36_0 jupyter_core 4.6.1 py36_0 kiwisolver 1.1.0 py36ha925a31_0 lazy-object-proxy 1.4.3 py36he774522_0 libiconv 1.15 h1df5818_7 libpng 1.6.37 h2a8f88b_0 libsodium 1.0.16 h9d3ae62_0 libtiff 4.1.0 h56a325e_0 libxml2 2.9.9 h464c3ec_0 libxslt 1.1.33 h579f668_0 lxml 4.4.2 py36h1350720_0 macholib 1.11 py_0 markupsafe 1.1.1 py36he774522_0 matplotlib 3.1.1 py36hc8f65d3_0 mccabe 0.6.1 py36_1 mkl 2019.4 245 mkl-service 2.3.0 py36hb782905_0 mkl_fft 1.0.15 py36h14836fe_0 mkl_random 1.1.0 py36h675688f_0 more-itertools 8.0.2 py_0 nodeenv 1.3.4 py_0 conda-forge numpy 1.17.4 py36h4320e6b_0 numpy-base 1.17.4 py36hc3f5095_0 olefile 0.46 py36_0 openssl 1.1.1d he774522_3 owslib 0.18.0 py_0 packaging 20.0 py_0 pandas 0.25.3 py36ha925a31_0 parso 0.5.2 py_0 pefile 2019.4.18 py_0 pickleshare 0.7.5 py36_0 pillow 7.0.0 py36hcc1f983_0 pip 19.3.1 py36_0 pluggy 0.13.1 py36_0 pre-commit 1.21.0 py36_0 conda-forge proj4 5.2.0 ha925a31_1 prompt_toolkit 3.0.2 py_0 py 1.8.1 py_0 py-cpuinfo 5.0.0 py_0 pycodestyle 2.5.0 py36_0 pycparser 2.19 py36_0 pycrypto 2.6.1 py36hfa6e2cd_9 pyepsg 0.4.0 py36_0 pyflakes 2.1.1 py36_0 pygments 2.5.2 py_0 pyinstaller 3.4 py36h2a8f88b_1 pykdtree 1.3.1 py36h8c2d366_2 pylint 2.4.4 py36_0 pyopenssl 19.1.0 py36_0 pyparsing 2.4.6 py_0 pyproj 1.9.6 py36h6782396_0 pyqt 5.9.2 py36h6538335_2 pyshp 2.1.0 py_0 pysocks 1.7.1 py36_0 pytest 5.3.2 py36_0 pytest-benchmark 3.2.2 py36_0 pytest-cov 2.8.1 py_0 pytest-flake8 1.0.4 py36_0 conda-forge pytest-forked 1.1.3 py_0 pytest-pylint 0.14.1 py_0 conda-forge pytest-runner 5.2 py_0 pytest-xdist 1.30.0 py_0 python 3.6.10 h9f7ef89_0 python-dateutil 2.8.1 py_0 python-pptx 0.6.18 py_0 conda-forge pytz 2019.3 py_0 pywin32 227 py36he774522_0 pywin32-ctypes 0.2.0 py36_0 pyyaml 5.2 py36he774522_0 pyzmq 18.1.0 py36ha925a31_0 qt 5.9.7 vc14h73c81de_0 requests 2.22.0 py36_1 scikit-learn 0.22.1 py36h6288b17_0 scipy 1.3.2 py36h29ff71c_0 setuptools 44.0.0 py36_0 shapely 1.6.4 py36h222a598_0 simplekml 1.3.1 pypi_0 pypi sip 4.19.8 py36h6538335_0 six 1.13.0 py36_0 snowballstemmer 2.0.0 py_0 sphinx 2.3.1 py_0 sphinxcontrib-applehelp 1.0.1 py_0 sphinxcontrib-devhelp 1.0.1 py_0 sphinxcontrib-htmlhelp 1.0.2 py_0 sphinxcontrib-jsmath 1.0.1 py_0 sphinxcontrib-qthelp 1.0.2 py_0 sphinxcontrib-serializinghtml 1.1.3 py_0 spyder-kernels 1.8.1 py36_0 sqlite 3.30.1 he774522_0 tk 8.6.8 hfa6e2cd_0 toml 0.10.0 py36h28b3542_0 tornado 6.0.3 py36he774522_0 tox 2.8.1 py36_0 conda-forge tqdm 4.40.2 py_0 traitlets 4.3.3 py36_0 typed-ast 1.4.0 py36he774522_0 urllib3 1.25.7 py36_0 vc 14.1 h0510ff6_4 virtualenv 16.7.5 py_0 vs2015_runtime 14.16.27012 hf0eaf9b_1 wcwidth 0.1.7 py36_0 wheel 0.33.6 py36_0 win_inet_pton 1.1.0 py36_0 wincertstore 0.2 py36h7fe50ca_0 wrapt 1.11.2 py36he774522_0 xlsxwriter 1.2.7 py_0 xz 5.2.4 h2fa13f4_4 yaml 0.1.7 hc54c509_2 yapf 0.28.0 py_0 zeromq 4.3.1 h33f27b4_3 zipp 0.6.0 py_0 zlib 1.2.11 h62dcd97_3 zstd 1.3.7 h508b16e_0 ``` ### pip list ``` Package Version Location ----------------------------- ------------------- ------------------------------------------------------------------ alabaster 0.7.12 altgraph 0.16.1 apipkg 1.5 asn1crypto 1.2.0 aspy.yaml 1.3.0 astroid 2.3.3 atomicwrites 1.3.0 attrs 19.3.0 autopep8 1.4.4 Babel 2.8.0 backcall 0.1.0 cached-property 1.5.1 Cartopy 0.17.0 certifi 2019.11.28 cffi 1.13.2 cfgv 2.0.1 chardet 3.0.4 cloudpickle 1.2.2 colorama 0.4.3 construct 2.9.45 coverage 5.0 cryptography 2.8 cycler 0.10.0 Cython 0.29.14 decorator 4.4.1 docutils 0.15.2 editdistance 0.5.3 entrypoints 0.3 execnet 1.7.1 flake8 3.7.9 future 0.18.2 identify 1.4.9 idna 2.8 imagesize 1.2.0 importlib-metadata 1.3.0 importlib-resources 1.0.2 ipykernel 5.1.3 ipython 7.11.1 ipython-genutils 0.2.0 isort 4.3.21 jedi 0.15.2 Jinja2 2.10.3 joblib 0.14.1 jupyter-client 5.3.4 jupyter-core 4.6.1 kiwisolver 1.1.0 lazy-object-proxy 1.4.3 lxml 4.4.2 macholib 1.11 MarkupSafe 1.1.1 matplotlib 3.1.1 mccabe 0.6.1 mkl-fft 1.0.15 mkl-random 1.1.0 mkl-service 2.3.0 more-itertools 8.0.2 nodeenv 1.3.4 numpy 1.17.4 olefile 0.46 OWSLib 0.18.0 packaging 20.0 pandas 0.25.3 parso 0.5.2 pefile 2019.4.18 pickleshare 0.7.5 Pillow 7.0.0 pip 19.3.1 pluggy 0.13.1 pre-commit 1.21.0 prompt-toolkit 3.0.2 py 1.8.1 py-cpuinfo 5.0.0 pycodestyle 2.5.0 pycparser 2.19 pycrypto 2.6.1 pyepsg 0.4.0 pyflakes 2.1.1 Pygments 2.5.2 PyInstaller 3.4 pykdtree 1.3.1 pylint 2.4.4 pyOpenSSL 19.1.0 pyparsing 2.4.6 pyproj 1.9.6 pyshp 2.1.0 PySocks 1.7.1 pytest 5.3.2 pytest-benchmark 3.2.2 pytest-cov 2.8.1 pytest-flake8 1.0.4 pytest-forked 1.1.3 pytest-pylint 0.14.1 pytest-runner 5.2 pytest-xdist 1.30.0 python-dateutil 2.8.1 python-pptx 0.6.18 pytz 2019.3 pywin32 227 pywin32-ctypes 0.2.0 PyYAML 5.2 pyzmq 18.1.0 requests 2.22.0 scikit-learn 0.22.1 scipy 1.3.2 setuptools 44.0.0.post20200106 Shapely 1.6.4.post1 simplekml 1.3.1 six 1.13.0 snowballstemmer 2.0.0 Sphinx 2.3.1 sphinxcontrib-applehelp 1.0.1 sphinxcontrib-devhelp 1.0.1 sphinxcontrib-htmlhelp 1.0.2 sphinxcontrib-jsmath 1.0.1 sphinxcontrib-qthelp 1.0.2 sphinxcontrib-serializinghtml 1.1.3 spyder-kernels 1.8.1 toml 0.10.0 tornado 6.0.3 tox 2.8.1 tqdm 4.40.2 traitlets 4.3.3 typed-ast 1.4.0 urllib3 1.25.7 virtualenv 16.7.5 wcwidth 0.1.7 wheel 0.33.6 win-inet-pton 1.1.0 wincertstore 0.2 wrapt 1.11.2 XlsxWriter 1.2.7 yapf 0.28.0 zipp 0.6.0 ```
QuLogic commented 4 years ago

1000 seems to be a very suspiciously round number, but I don't see anything that seems to mention it.

sagrawal-idrc commented 4 years ago

Related to an issue I opened last year: https://github.com/SciTools/cartopy/issues/1357

dopplershift commented 4 years ago

So the root problem is that given the data here (things in order and > 1000 points) we're triggering an optimization in matplotlib for lines--on that doesn't work for us since our transforms are not generally rectilinear. The fix is to set the axes name to something other than 'rectilinear'. That should also give a workaround for any who need it, just:

ax.name = 'cartopy'

I'll send in a PR in a second.