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.42k stars 362 forks source link

Adjusting tolerance for add_cyclic_point #1276

Open nick-klingaman opened 5 years ago

nick-klingaman commented 5 years ago

Description

The current version of cartopy_util.add_cyclic_point() requires that coordinates be (nearly) exactly regularly spaced. It computes the difference between consecutive values of the coordinate array, then passes these to np.allclose() to determine if the differences are (highly) similar. np.allclose() uses a default tolerance of 1e-8, which may be beyond the precision of the coordinate array itself. This means that coordinates which are even slightly irregularly spaced -- possibly even due to precision/rounding errors -- cannot be used with add_cyclic_point().

Would it be possible to pass a user-defined tolerance to np.allclose() through cartopy, or allow for very small variations in spacing in some other way? For instance, the longitude coordinate spacing in one of my datasets varies by approximately 1e-5 degrees. I can overwrite the coordinate with a coordinate that is more exactly regularly spaced, but this seems clunky.

It looks like a similar issue was reported in #398, but this was closed without a solution for irregularly spaced grids.

Code to reproduce

Traceback

field, x = cartopy_util.add_cyclic_point(field, x)
  File "/home/users/npklingaman/klingaman_virtualenv/venv/lib/python2.7/site-packages/cartopy/util.py", line 101, in add_cyclic_point
    raise ValueError('The coordinate must be equally spaced.')
ValueError: The coordinate must be equally spaced.
Full environment definition ### Operating system Linux x86-64 ### Cartopy version 0.17.0 ### conda list ``` ``` ### pip list ``` affine 2.2.2 asn1crypto 0.24.0 attrs 18.2.0 backports.functools-lru-cache 1.5 basemap 1.0.7 Biggus 0.14.0 Cartopy 0.17.0 cdsapi 0.1.3 certifi 2018.11.29 cf-plot 2.2.18 cf-python 2.3.2 cf-units 2.1.1 cffi 1.12.0 cftime 1.0.3.4 chardet 3.0.4 Click 7.0 click-plugins 1.0.4 cligj 0.5.0 cryptography 2.5 cycler 0.10.0 Cython 0.29.5 dask 1.1.1 descartes 1.1.0 dreqPy 1.0.29 eccodes 2.8.0 enum34 1.1.6 findiff 0.6.2 Fiona 1.7.13 functools32 3.2.3.post2 geopandas 0.4.0 Glances 3.1.0 graphviz 0.10.1 htmltemplate 2.2.0 idna 2.8 ipaddress 1.0.22 iris-grib 0.13.0 joblib 0.13.2 kiwisolver 1.0.1 matplotlib 2.2.3 mo-pack 0.2.0 motionless 1.3.2 mule 2017.8.1 munch 2.3.2 netCDF4 1.4.2 netcdftime 1.0.0a2 numpy 1.16.1 olefile 0.46 pandas 0.24.1 PIL 1.1.7 Pillow 5.4.1 pip 19.0.2 psutil 5.5.0 pycparser 2.19 pyke 1.1.1 pyOpenSSL 19.0.0 pyparsing 2.3.1 pyproj 1.9.6 pyshp 2.0.1 pyspharm 1.0.8 python-dateutil 2.8.0 pytz 2018.9 pyugrid 0.3.1 rasterio 1.0.18 requests 2.21.0 s-tui 0.8.3 salem 0.2.3 scipy 1.2.1 scitools-iris 2.2.0 setuptools 32.1.3 Shapely 1.6.4.post2 six 1.12.0 snuggs 1.4.2 subprocess32 3.5.3 toolz 0.9.0 urllib3 1.24.1 urwid 2.0.1 windspharm 1.7.0 xarray 0.11.3 XlsxWriter 1.1.4 ```
ajdawson commented 5 years ago

Hi @nick-klingaman, yes in principle we could support keywords to allow control of the tolerance check. The np.allclose function supports setting relative and absolute tolerances which could be passed through from add_cyclic_point (https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.allclose.html). Pull requests are always welcome.