From 79d5fc2952163b73c013be19bbda135c130a68c5 Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Thu, 16 Sep 2021 20:26:07 -0600 Subject: [PATCH] MNT: Update imports for dependencies Change all scipy imports to lazily load and provide a useful ImportError if it isn't available. Move Matplotlib into a required dependency. --- INSTALL | 8 ++++---- lib/cartopy/img_transform.py | 6 +++++- lib/cartopy/mpl/geoaxes.py | 15 ++++++++++++--- lib/cartopy/vector_transform.py | 5 ++++- requirements/default.txt | 1 + requirements/plotting.txt | 1 - 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/INSTALL b/INSTALL index 7d9abf7e1..3dc34faa0 100644 --- a/INSTALL +++ b/INSTALL @@ -79,6 +79,10 @@ Further information about the required dependencies can be found here: **Python** 3.7 or later (https://www.python.org/) Python 2 support was removed in v0.19. +**Matplotlib** 3.1 or later (https://matplotlib.org/) + Python package for 2D plotting. Python package required for any + graphical capabilities. + **GEOS** 3.7.2 or later (https://trac.osgeo.org/geos/) GEOS is an API of spatial predicates and functions for processing geometry written in C++. @@ -102,10 +106,6 @@ Optional Dependencies To make the most of Cartopy by enabling additional functionality, you may want to install these optional dependencies. -**Matplotlib** 3.1 or later (https://matplotlib.org/) - Python package for 2D plotting. Python package required for any - graphical capabilities. - **GDAL** version 2.3.2 (https://gdal.org/) GDAL is a translator library for raster and vector geospatial data formats, which has powerful data transformation and processing capabilities. diff --git a/lib/cartopy/img_transform.py b/lib/cartopy/img_transform.py index 3865a6c05..2ddf61641 100644 --- a/lib/cartopy/img_transform.py +++ b/lib/cartopy/img_transform.py @@ -14,7 +14,11 @@ import pykdtree.kdtree _is_pykdtree = True except ImportError: - import scipy.spatial + try: + import scipy.spatial + except ImportError as e: + raise ImportError("Using image transforms requires either " + "pykdtree or scipy.") from e _is_pykdtree = False import cartopy.crs as ccrs diff --git a/lib/cartopy/mpl/geoaxes.py b/lib/cartopy/mpl/geoaxes.py index d053d6834..5a9ca7b6c 100644 --- a/lib/cartopy/mpl/geoaxes.py +++ b/lib/cartopy/mpl/geoaxes.py @@ -34,13 +34,11 @@ from cartopy import config import cartopy.crs as ccrs import cartopy.feature -import cartopy.img_transform import cartopy.mpl.contour import cartopy.mpl.geocollection import cartopy.mpl.feature_artist as feature_artist import cartopy.mpl.patch as cpatch from cartopy.mpl.slippy_image_artist import SlippyImageArtist -from cartopy.vector_transform import vector_scalar_to_grid assert mpl.__version__ >= '3.1', \ @@ -1371,7 +1369,9 @@ def imshow(self, img, *args, **kwargs): regrid_shape = kwargs.pop('regrid_shape', 750) regrid_shape = self._regrid_shape_aspect(regrid_shape, target_extent) - warp_array = cartopy.img_transform.warp_array + # Lazy import because scipy/pykdtree in img_transform are only + # optional dependencies + from cartopy.img_transform import warp_array original_extent = extent img, extent = warp_array(img, source_proj=transform, @@ -2073,6 +2073,9 @@ def quiver(self, x, y, u, v, *args, **kwargs): # manually and plotting in native coordinates. regrid_shape = self._regrid_shape_aspect(regrid_shape, target_extent) + # Lazy load vector_scalar_to_grid due to the optional + # scipy dependency + from cartopy.vector_transform import vector_scalar_to_grid if args: # Interpolate color array as well as vector components. x, y, u, v, c = vector_scalar_to_grid( @@ -2145,6 +2148,9 @@ def barbs(self, x, y, u, v, *args, **kwargs): # manually and plotting in native coordinates. regrid_shape = self._regrid_shape_aspect(regrid_shape, target_extent) + # Lazy load vector_scalar_to_grid due to the optional + # scipy dependency + from cartopy.vector_transform import vector_scalar_to_grid if args: # Interpolate color array as well as vector components. x, y, u, v, c = vector_scalar_to_grid( @@ -2218,6 +2224,9 @@ def streamplot(self, x, y, u, v, **kwargs): scalars.append(lw) # Do the regridding including any scalar fields. target_extent = self.get_extent(self.projection) + # Lazy load vector_scalar_to_grid due to the optional + # scipy dependency + from cartopy.vector_transform import vector_scalar_to_grid gridded = vector_scalar_to_grid(t, self.projection, regrid_shape, x, y, u, v, *scalars, target_extent=target_extent) diff --git a/lib/cartopy/vector_transform.py b/lib/cartopy/vector_transform.py index 2be84ff93..fc39e2c10 100644 --- a/lib/cartopy/vector_transform.py +++ b/lib/cartopy/vector_transform.py @@ -10,7 +10,10 @@ """ import numpy as np -from scipy.interpolate import griddata +try: + from scipy.interpolate import griddata +except ImportError as e: + raise ImportError("Regridding vectors requires scipy.") from e def _interpolate_to_grid(nx, ny, x, y, *scalars, **kwargs): diff --git a/requirements/default.txt b/requirements/default.txt index 13ec9ab8e..861450c3c 100644 --- a/requirements/default.txt +++ b/requirements/default.txt @@ -1,4 +1,5 @@ numpy>=1.18 +matplotlib>=3.1 shapely>=1.6.4 pyshp>=2.1 pyproj>=3.0.0 diff --git a/requirements/plotting.txt b/requirements/plotting.txt index 62e98ac3e..f75b59f68 100644 --- a/requirements/plotting.txt +++ b/requirements/plotting.txt @@ -1,4 +1,3 @@ -matplotlib>=3.1 GDAL>=2.3.2 pillow>=6.1.0 scipy>=1.3.1