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 365 forks source link

Longitude gridlines no longer contrained to the latitude gridline range (and vice versa) in cartopy 0.18 #1568

Closed lukelbd closed 4 years ago

lukelbd commented 4 years ago

Description

In cartopy 0.17, longitude gridlines were constrained within the region of the minumum and maximum latitude gridlines, and latitude gridlines were constrained within the region of the minimum and maximum longitude gridlines.

This was very useful for "pole" centered projections, as it let people mimic the "latmax" feature used in polar basemap projections. Generally it's nice to have a "hole" around the North and South poles rather than having all the gridlines converge to a single point.

In cartopy v0.18, this gridlining behavior seems to have disappeared -- putting a "hole" around the North and South poles is no longer possible.

Code to reproduce

import cartopy
import cartopy.crs as ccrs
import numpy as np
import matplotlib.pyplot as plt
import cartopy.feature as cfeature
import matplotlib.ticker as mticker
lats = mticker.FixedLocator(np.arange(-80, 81, 5))
lons = mticker.MultipleLocator(60)
fig = plt.figure(figsize=(6, 3))

ax = fig.add_subplot(121, projection=ccrs.NorthPolarStereo())
ax.set_extent([-180, 180, 70, 90], crs=ccrs.PlateCarree())
ax.gridlines(xlocs=lons, ylocs=lats)
ax.add_feature(cfeature.COASTLINE)

ax = fig.add_subplot(122, projection=ccrs.SouthPolarStereo())
ax.set_extent([-180, 180, -90, -70], crs=ccrs.PlateCarree())
ax.gridlines(xlocs=lons, ylocs=lats)
ax.add_feature(cfeature.COASTLINE)

fig.suptitle(f'Gridlines over polar projections in cartopy v{cartopy.__version__}')

Results in the following for cartopy 0.17:

tmp

And the following for cartopy 0.18:

tmp

Full environment definition ### Cartopy version v0.17 and v0.18 ### conda list ``` # packages in environment at /Users/ldavis/miniconda3: # # Name Version Build Channel alabaster 0.7.12 pypi_0 pypi appdirs 1.4.4 pypi_0 pypi appnope 0.1.0 py38h32f6830_1001 conda-forge asttokens 2.0.4 pypi_0 pypi attrs 19.3.0 py_0 conda-forge autopep8 1.5.2 pypi_0 pypi babel 2.8.0 pypi_0 pypi backcall 0.1.0 py_0 conda-forge basemap 1.3.0 py38h9bcff04_2 conda-forge basemap-data-hires 1.2.1 0 conda-forge beautifulsoup4 4.9.0 pypi_0 pypi black 19.10b0 pypi_0 pypi bleach 3.1.5 pyh9f0ad1d_0 conda-forge boost-cpp 1.72.0 hdf9ef73_0 conda-forge brotlipy 0.7.0 py38h64e0658_1000 conda-forge bs4 0.0.1 pypi_0 pypi bzip2 1.0.8 h0b31af3_2 conda-forge ca-certificates 2020.4.5.1 hecc5488_0 conda-forge cairo 1.16.0 hec6a9b0_1003 conda-forge cartopy 0.17.0 py38h9bcff04_1015 conda-forge certifi 2020.4.5.1 py38h32f6830_0 conda-forge cffi 1.14.0 py38h356ff06_0 conda-forge cfgv 3.1.0 pypi_0 pypi cfitsio 3.470 hddc9c06_5 conda-forge cftime 1.1.2 py38h65ad66c_0 conda-forge chardet 3.0.4 py38h32f6830_1006 conda-forge click 7.1.2 pypi_0 pypi climpy 0.0.3.post56+dirty dev_0 colorama 0.4.3 pypi_0 pypi conda 4.8.3 py38h32f6830_1 conda-forge conda-package-handling 1.6.0 py38h64e0658_2 conda-forge cryptography 2.9.2 py38hb761dab_0 conda-forge ctags 5.8 h1de35cc_1000 conda-forge curl 7.69.1 h2d98d24_0 conda-forge cycler 0.10.0 py_2 conda-forge dbus 1.13.6 h2f22bb5_0 conda-forge decorator 4.4.2 py_0 conda-forge defusedxml 0.6.0 py_0 conda-forge discogs-client 2.2.2 pypi_0 pypi distlib 0.3.0 pypi_0 pypi docopt 0.6.2 pypi_0 pypi docutils 0.16 pypi_0 pypi entrypoints 0.3 py38h32f6830_1001 conda-forge executing 0.4.3 pypi_0 pypi expat 2.2.9 h4a8c4bd_2 conda-forge ffmpeg-normalize 1.19.0 pypi_0 pypi filelock 3.0.12 pypi_0 pypi flake8 3.8.1 pypi_0 pypi flake8-unused-arguments 0.0.3 pypi_0 pypi fontconfig 2.13.1 h6b1039f_1001 conda-forge freetype 2.10.1 h8da9a1a_0 conda-forge freexl 1.0.5 h1de35cc_1002 conda-forge gdal 3.0.4 py38h9f7df5a_10 conda-forge geos 3.8.1 h4a8c4bd_0 conda-forge geotiff 1.6.0 hd8796ba_0 conda-forge gettext 0.19.8.1 h46ab8bc_1002 conda-forge giflib 5.2.1 h0b31af3_2 conda-forge glib 2.64.2 h577aef8_0 conda-forge greenlet 0.4.15 pypi_0 pypi hdf4 4.2.13 h84186c3_1003 conda-forge hdf5 1.10.6 nompi_h3e39495_100 conda-forge icecream 2.0.0 pypi_0 pypi icu 64.2 h6de7cb9_1 conda-forge identify 1.4.15 pypi_0 pypi idna 2.9 py_1 conda-forge imagesize 1.2.0 pypi_0 pypi importlib-metadata 1.6.0 py38h32f6830_0 conda-forge importlib_metadata 1.6.0 0 conda-forge ipykernel 5.2.1 py38h23f93f0_0 conda-forge ipython 7.14.0 py38h32f6830_0 conda-forge ipython_genutils 0.2.0 py_1 conda-forge ipywidgets 7.5.1 py_0 conda-forge jedi 0.17.0 py38h32f6830_0 conda-forge jinja2 2.11.2 pyh9f0ad1d_0 conda-forge jpeg 9c h1de35cc_1001 conda-forge json-c 0.13.1 h1de35cc_1001 conda-forge jsonschema 3.2.0 py38h32f6830_1 conda-forge jupyter 1.0.0 py_2 conda-forge jupyter-contrib-core 0.3.3 pypi_0 pypi jupyter-nbextensions-configurator 0.4.1 pypi_0 pypi jupyter_client 6.1.3 py_0 conda-forge jupyter_console 6.1.0 py_1 conda-forge jupyter_core 4.6.3 py38h32f6830_1 conda-forge jupyterthemes 0.20.0 pypi_0 pypi jupytext 1.4.2 pypi_0 pypi kealib 1.4.13 h40102fb_1 conda-forge keyring 21.2.1 pypi_0 pypi kiwisolver 1.2.0 py38ha0d09dd_0 conda-forge krb5 1.17.1 h1752a42_0 conda-forge lesscpy 0.14.0 pypi_0 pypi libblas 3.8.0 16_openblas conda-forge libcblas 3.8.0 16_openblas conda-forge libclang 9.0.1 default_hf57f61e_0 conda-forge libcurl 7.69.1 hc0b9707_0 conda-forge libcxx 10.0.0 h1af66ff_2 conda-forge libdap4 3.20.6 h8c15375_0 conda-forge libedit 3.1.20170329 hcfe32e1_1001 conda-forge libffi 3.2.1 h4a8c4bd_1007 conda-forge libgdal 3.0.4 h242383b_10 conda-forge libgfortran 4.0.0 2 conda-forge libiconv 1.15 h0b31af3_1006 conda-forge libkml 1.3.0 h169b8f9_1011 conda-forge liblapack 3.8.0 16_openblas conda-forge libllvm9 9.0.1 h7475705_1 conda-forge libnetcdf 4.7.4 nompi_ha11d67f_104 conda-forge libopenblas 0.3.9 h3d69b6c_0 conda-forge libpng 1.6.37 hbbe82c9_1 conda-forge libpq 12.2 h489d428_1 conda-forge libsodium 1.0.17 h01d97ff_0 conda-forge libspatialite 4.3.0a h658e6c1_1038 conda-forge libssh2 1.8.2 hcdc9a53_2 conda-forge libtiff 4.1.0 h2ae36a8_6 conda-forge libwebp-base 1.1.0 h0b31af3_3 conda-forge libxml2 2.9.10 h53d96d6_0 conda-forge llvm-openmp 10.0.0 h28b9765_0 conda-forge lz4-c 1.9.2 h4a8c4bd_1 conda-forge markupsafe 1.1.1 py38h64e0658_1 conda-forge matplotlib 3.2.0 pypi_0 pypi matplotlib-base 3.2.1 py38h1300a51_0 conda-forge mccabe 0.6.1 pypi_0 pypi mistune 0.8.4 py38h64e0658_1001 conda-forge msgpack 1.0.0 pypi_0 pypi musicbrainzngs 0.7.1 pypi_0 pypi mutagen 1.44.0 pypi_0 pypi nbconvert 5.6.1 py38h32f6830_1 conda-forge nbformat 5.0.6 py_0 conda-forge nbsphinx 0.6.1 pypi_0 pypi ncurses 6.1 h0a44026_1002 conda-forge neovim 0.3.1 pypi_0 pypi netcdf4 1.5.3 nompi_py38h4c5c689_105 conda-forge nodeenv 1.3.5 pypi_0 pypi notebook 6.0.3 py38h32f6830_0 conda-forge nspr 4.20 h0a44026_1000 conda-forge nss 3.47 hc0980d9_0 conda-forge numpy 1.18.4 py38h1f821a2_0 conda-forge oauthlib 3.1.0 pypi_0 pypi olefile 0.46 py_0 conda-forge openjpeg 2.3.1 h254dc36_3 conda-forge openssl 1.1.1g h0b31af3_0 conda-forge owslib 0.19.2 py_1 conda-forge packaging 20.1 py_0 conda-forge pandas 1.0.3 py38h5fc983b_1 conda-forge pandoc 1.0.2 pypi_0 pypi pandocfilters 1.4.2 pypi_0 pypi parso 0.7.0 pyh9f0ad1d_0 conda-forge pathspec 0.8.0 pypi_0 pypi pcre 8.44 h4a8c4bd_0 conda-forge pexpect 4.8.0 py38h32f6830_1 conda-forge pickleshare 0.7.5 py38h32f6830_1001 conda-forge pillow 7.1.2 py38h83dc5e5_0 conda-forge pip 20.1 pyh9f0ad1d_0 conda-forge pixman 0.38.0 h01d97ff_1003 conda-forge pkginfo 1.5.0.1 pypi_0 pypi ply 3.11 pypi_0 pypi poppler 0.87.0 h3232a60_1 conda-forge poppler-data 0.4.9 1 conda-forge postgresql 12.2 h62ab893_1 conda-forge pre-commit 2.3.0 pypi_0 pypi proj 7.0.0 hbce2d5c_3 conda-forge prometheus_client 0.7.1 py_0 conda-forge prompt-toolkit 3.0.5 py_0 conda-forge prompt_toolkit 3.0.5 0 conda-forge proplot 0.6.0 dev_0 ptyprocess 0.6.0 py_1001 conda-forge pycodestyle 2.6.0 pypi_0 pypi pycosat 0.6.3 py38h64e0658_1004 conda-forge pycparser 2.20 py_0 conda-forge pyepsg 0.4.0 py_0 conda-forge pyflakes 2.2.0 pypi_0 pypi pygments 2.6.1 py_0 conda-forge pykdtree 1.3.1 py38h65ad66c_1003 conda-forge pynvim 0.4.1 pypi_0 pypi pyopenssl 19.1.0 py_1 conda-forge pyparsing 2.4.7 pyh9f0ad1d_0 conda-forge pyproj 2.6.1.post1 py38h7d7e87d_0 conda-forge pyqt 5.12.3 py38hf180056_3 conda-forge pyqt5 5.14.2 pypi_0 pypi pyqt5-sip 4.19.18 pypi_0 pypi pyqtchart 5.12 pypi_0 pypi pyqtwebengine 5.12.1 pypi_0 pypi pyrsistent 0.16.0 py38h64e0658_0 conda-forge pyshp 2.1.0 py_0 conda-forge pysocks 1.7.1 py38h32f6830_1 conda-forge python 3.8.2 hd5f0129_7_cpython conda-forge python-dateutil 2.8.1 py_0 conda-forge python.app 2 py38_10 defaults python_abi 3.8 1_cp38 conda-forge pytz 2020.1 pyh9f0ad1d_0 conda-forge pyyaml 5.3.1 pypi_0 pypi pyzmq 19.0.1 py38h1fcdcd6_0 conda-forge qt 5.12.5 h514805e_3 conda-forge qtconsole 4.7.3 pyh9f0ad1d_0 conda-forge qtpy 1.9.0 py_0 conda-forge readline 8.0 hcfe32e1_0 conda-forge readme-renderer 26.0 pypi_0 pypi regex 2020.4.4 pypi_0 pypi requests 2.23.0 pyh8c360ce_2 conda-forge requests-toolbelt 0.9.1 pypi_0 pypi ruamel_yaml 0.15.80 py38h64e0658_1001 conda-forge scipy 1.4.1 py38h38b60c6_3 conda-forge send2trash 1.5.0 py_0 conda-forge setuptools 46.1.3 py38h32f6830_0 conda-forge shapely 1.7.0 py38h5b1fbde_3 conda-forge six 1.14.0 py_1 conda-forge snowballstemmer 2.0.0 pypi_0 pypi soupsieve 2.0 pypi_0 pypi sphinx 3.0.3 pypi_0 pypi sphinx-automodapi 0.6.proplot-mods dev_0 sphinx-copybutton 0.2.11 pypi_0 pypi sphinx-rtd-theme 0.4.3 pypi_0 pypi sphinxcontrib-applehelp 1.0.2 pypi_0 pypi sphinxcontrib-devhelp 1.0.2 pypi_0 pypi sphinxcontrib-htmlhelp 1.0.3 pypi_0 pypi sphinxcontrib-jsmath 1.0.1 pypi_0 pypi sphinxcontrib-qthelp 1.0.3 pypi_0 pypi sphinxcontrib-serializinghtml 1.1.4 pypi_0 pypi sqlite 3.30.1 h93121df_0 conda-forge tbb 2018.0.5 h2d50403_0 conda-forge terminado 0.8.3 py38h32f6830_1 conda-forge testpath 0.4.4 py_0 conda-forge tiledb 1.7.7 h84aa2a7_1 conda-forge tk 8.6.10 hbbe82c9_0 conda-forge toml 0.10.0 pypi_0 pypi tornado 6.0.4 py38h64e0658_1 conda-forge tqdm 4.46.0 pyh9f0ad1d_0 conda-forge traitlets 4.3.3 py38h32f6830_1 conda-forge twine 3.1.1 pypi_0 pypi typed-ast 1.4.1 pypi_0 pypi tzcode 2020a h0b31af3_0 conda-forge unidecode 1.1.1 pypi_0 pypi urllib3 1.25.9 py_0 conda-forge vim 8.2.0694 py38h2782e99_0 conda-forge vint 0.1.5 pypi_0 pypi virtualenv 20.0.20 pypi_0 pypi wcwidth 0.1.9 pyh9f0ad1d_0 conda-forge webencodings 0.5.1 pypi_0 pypi wheel 0.34.2 py_1 conda-forge widgetsnbextension 3.5.1 py38_0 conda-forge xarray 0.15.1 py_0 conda-forge xerces-c 3.2.2 h8f8adb3_1004 conda-forge xz 5.2.5 h0b31af3_0 conda-forge yaml 0.2.4 h0b31af3_0 conda-forge youtube-dl 2020.5.8 pypi_0 pypi zeromq 4.3.2 h6de7cb9_2 conda-forge zipp 3.1.0 py_0 conda-forge zlib 1.2.11 h0b31af3_1006 conda-forge zstd 1.4.4 h4b3e974_3 conda-forge ``` ### pip list ``` Package Version Location --------------------------------- ------------------- ------------------------------- alabaster 0.7.12 appdirs 1.4.4 appnope 0.1.0 asttokens 2.0.4 attrs 19.3.0 autopep8 1.5.2 Babel 2.8.0 backcall 0.1.0 basemap 1.2.1 beautifulsoup4 4.9.0 black 19.10b0 bleach 3.1.5 brotlipy 0.7.0 bs4 0.0.1 Cartopy 0.17.0 certifi 2020.4.5.1 cffi 1.14.0 cfgv 3.1.0 cftime 1.1.2 chardet 3.0.4 click 7.1.2 climpy 0.0.3.post56+dirty /Users/ldavis/climpy colorama 0.4.3 conda 4.8.3 conda-package-handling 1.6.0 cryptography 2.9.2 cycler 0.10.0 decorator 4.4.2 defusedxml 0.6.0 discogs-client 2.2.2 distlib 0.3.0 docopt 0.6.2 docutils 0.16 entrypoints 0.3 executing 0.4.3 ffmpeg-normalize 1.19.0 filelock 3.0.12 flake8 3.8.1 flake8-unused-arguments 0.0.3 GDAL 3.0.4 greenlet 0.4.15 icecream 2.0.0 identify 1.4.15 idna 2.9 imagesize 1.2.0 importlib-metadata 1.6.0 ipykernel 5.2.1 ipython 7.14.0 ipython-genutils 0.2.0 ipywidgets 7.5.1 jedi 0.17.0 Jinja2 2.11.2 jsonschema 3.2.0 jupyter-client 6.1.3 jupyter-console 6.1.0 jupyter-contrib-core 0.3.3 jupyter-core 4.6.3 jupyter-nbextensions-configurator 0.4.1 jupyterthemes 0.20.0 jupytext 1.4.2 keyring 21.2.1 kiwisolver 1.2.0 lesscpy 0.14.0 MarkupSafe 1.1.1 matplotlib 3.2.1 mccabe 0.6.1 mistune 0.8.4 msgpack 1.0.0 musicbrainzngs 0.7.1 mutagen 1.44.0 nbconvert 5.6.1 nbformat 5.0.6 nbsphinx 0.6.1 neovim 0.3.1 netCDF4 1.5.3 nodeenv 1.3.5 notebook 6.0.3 numpy 1.18.4 oauthlib 3.1.0 olefile 0.46 OWSLib 0.19.2 packaging 20.1 pandas 1.0.3 pandoc 1.0.2 pandocfilters 1.4.2 parso 0.7.0 pathspec 0.8.0 pexpect 4.8.0 pickleshare 0.7.5 Pillow 7.1.2 pip 20.1 pkginfo 1.5.0.1 ply 3.11 pre-commit 2.3.0 prometheus-client 0.7.1 prompt-toolkit 3.0.5 proplot 0.6.0 /Users/ldavis/proplot ptyprocess 0.6.0 pycodestyle 2.6.0 pycosat 0.6.3 pycparser 2.20 pyepsg 0.4.0 pyflakes 2.2.0 Pygments 2.6.1 pykdtree 1.3.1 pynvim 0.4.1 pyOpenSSL 19.1.0 pyparsing 2.4.7 pyproj 2.6.1.post1 PyQt5 5.14.2 PyQt5-sip 12.7.2 PyQtChart 5.12 PyQtWebEngine 5.12.1 pyrsistent 0.16.0 pyshp 2.1.0 PySocks 1.7.1 python-dateutil 2.8.1 pytz 2020.1 PyYAML 5.3.1 pyzmq 19.0.1 qtconsole 4.7.3 QtPy 1.9.0 readme-renderer 26.0 regex 2020.4.4 requests 2.23.0 requests-toolbelt 0.9.1 ruamel-yaml 0.15.80 scipy 1.4.1 Send2Trash 1.5.0 setuptools 46.1.3.post20200325 Shapely 1.7.0 six 1.14.0 snowballstemmer 2.0.0 soupsieve 2.0 Sphinx 3.0.3 sphinx-automodapi 0.6.proplot-mods /Users/ldavis/sphinx-automodapi sphinx-copybutton 0.2.11 sphinx-rtd-theme 0.4.3 sphinxcontrib-applehelp 1.0.2 sphinxcontrib-devhelp 1.0.2 sphinxcontrib-htmlhelp 1.0.3 sphinxcontrib-jsmath 1.0.1 sphinxcontrib-qthelp 1.0.3 sphinxcontrib-serializinghtml 1.1.4 terminado 0.8.3 testpath 0.4.4 toml 0.10.0 tornado 6.0.4 tqdm 4.46.0 traitlets 4.3.3 twine 3.1.1 typed-ast 1.4.1 Unidecode 1.1.1 urllib3 1.25.9 vint 0.1.5 virtualenv 20.0.20 wcwidth 0.1.9 webencodings 0.5.1 wheel 0.34.2 widgetsnbextension 3.5.1 xarray 0.15.1 youtube-dl 2020.5.8 zipp 3.1.0 ```
greglucas commented 4 years ago

@lukelbd I just opened a PR with an option to explicitly set a min/max for the gridlines. I think that is probably preferable to just automatically limiting the gridlines to the lon/lat range of the other gridlines, but I'd like to hear your thoughts on it too. I'm definitely open to suggestions on naming as well.