Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error plotting with cartopy & matplotlib #6927

Closed
4 tasks done
arfriedman opened this issue Aug 17, 2022 · 2 comments
Closed
4 tasks done

error plotting with cartopy & matplotlib #6927

arfriedman opened this issue Aug 17, 2022 · 2 comments

Comments

@arfriedman
Copy link
Contributor

What happened?

I am encountering an error while attempting to plot xarray fields using cartopy & matplotlib. [I'm posting here first but I'm not sure if the error is due to xarray, cartopy, or matplotlib].

What did you expect to happen?

Here is an example of the error using a plot from @rabernat's course: https://earth-env-data-science.github.io/lectures/mapping_cartopy.html#xarray-integration

Minimal Complete Verifiable Example

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import xarray as xr
url = 'http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/noaa.ersst.v5/sst.mnmean.nc'
ds = xr.open_dataset(url, drop_variables=['time_bnds'])
sst = ds.sst.sel(time='2000-01-01', method='nearest')
fig = plt.figure(figsize=(9,6))
ax = plt.axes(projection=ccrs.Robinson())
ax.coastlines()
ax.gridlines()
sst.plot(ax=ax, transform=ccrs.PlateCarree(),
         vmin=2, vmax=30)

MVCE confirmation

  • Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray.
  • Complete example — the example is self-contained, including all data and the text of any traceback.
  • Verifiable example — the example copy & pastes into an IPython prompt or Binder notebook, returning the result.
  • New issue — a search of GitHub Issues suggests this is not a duplicate.

Relevant log output

TypeError                                 Traceback (most recent call last)
Input In [12], in <cell line: 11>()
      9 ax.coastlines()
     10 ax.gridlines()
---> 11 sst.plot(ax=ax, transform=ccrs.PlateCarree(),
     12          vmin=2, vmax=30)

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/xarray/plot/plot.py:868, in _PlotMethods.__call__(self, **kwargs)
    867 def __call__(self, **kwargs):
--> 868     return plot(self._da, **kwargs)

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/xarray/plot/plot.py:334, in plot(darray, row, col, col_wrap, ax, hue, rtol, subplot_kws, **kwargs)
    330     plotfunc = hist
    332 kwargs["ax"] = ax
--> 334 return plotfunc(darray, **kwargs)

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/xarray/plot/plot.py:1212, in _plot2d.<locals>.newplotfunc(darray, x, y, figsize, size, aspect, ax, row, col, col_wrap, xincrease, yincrease, add_colorbar, add_labels, vmin, vmax, cmap, center, robust, extend, levels, infer_intervals, colors, subplot_kws, cbar_ax, cbar_kwargs, xscale, yscale, xticks, yticks, xlim, ylim, norm, **kwargs)
   1208     raise ValueError("plt.imshow's `aspect` kwarg is not available in xarray")
   1210 ax = get_axis(figsize, size, aspect, ax, **subplot_kws)
-> 1212 primitive = plotfunc(
   1213     xplt,
   1214     yplt,
   1215     zval,
   1216     ax=ax,
   1217     cmap=cmap_params["cmap"],
   1218     vmin=cmap_params["vmin"],
   1219     vmax=cmap_params["vmax"],
   1220     norm=cmap_params["norm"],
   1221     **kwargs,
   1222 )
   1224 # Label the plot with metadata
   1225 if add_labels:

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/xarray/plot/plot.py:1478, in pcolormesh(x, y, z, ax, xscale, yscale, infer_intervals, **kwargs)
   1475         y = _infer_interval_breaks(y, axis=1, scale=yscale)
   1476         y = _infer_interval_breaks(y, axis=0, scale=yscale)
-> 1478 primitive = ax.pcolormesh(x, y, z, **kwargs)
   1480 # by default, pcolormesh picks "round" values for bounds
   1481 # this results in ugly looking plots with lots of surrounding whitespace
   1482 if not hasattr(ax, "projection") and x.ndim == 1 and y.ndim == 1:
   1483     # not a cartopy geoaxis

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:318, in _add_transform.<locals>.wrapper(self, *args, **kwargs)
    313     raise ValueError(f'Invalid transform: Spherical {func.__name__} '
    314                      'is not supported - consider using '
    315                      'PlateCarree/RotatedPole.')
    317 kwargs['transform'] = transform
--> 318 return func(self, *args, **kwargs)

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:1799, in GeoAxes.pcolormesh(self, *args, **kwargs)
   1797 result = matplotlib.axes.Axes.pcolormesh(self, *args, **kwargs)
   1798 # Wrap the quadrilaterals if necessary
-> 1799 result = self._wrap_quadmesh(result, **kwargs)
   1800 # Re-cast the QuadMesh as a GeoQuadMesh to enable future wrapping
   1801 # updates to the collection as well.
   1802 result.__class__ = cartopy.mpl.geocollection.GeoQuadMesh

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:1982, in GeoAxes._wrap_quadmesh(self, collection, **kwargs)
   1968 # Plot all of the wrapped cells.
   1969 # `pcolor` only draws polygons where the data is not
   1970 # masked, so this will only draw a limited subset of
   (...)
   1978 #       fill in the proper data later with set_array()
   1979 #       calls.
   1980 pcolor_data = np.ma.array(np.zeros(C.shape),
   1981                           mask=~mask)
-> 1982 pcolor_col = self.pcolor(coords[..., 0], coords[..., 1],
   1983                          pcolor_data, zorder=zorder,
   1984                          **kwargs)
   1985 # Now add back in the masked data if there was any
   1986 full_mask = ~mask if C_mask is None else ~mask | C_mask

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:318, in _add_transform.<locals>.wrapper(self, *args, **kwargs)
    313     raise ValueError(f'Invalid transform: Spherical {func.__name__} '
    314                      'is not supported - consider using '
    315                      'PlateCarree/RotatedPole.')
    317 kwargs['transform'] = transform
--> 318 return func(self, *args, **kwargs)

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:2027, in GeoAxes.pcolor(self, *args, **kwargs)
   2024 result = matplotlib.axes.Axes.pcolor(self, *args, **kwargs)
   2026 # Update the datalim for this pcolor.
-> 2027 limits = result.get_datalim(self.transData)
   2028 self.update_datalim(limits)
   2030 self.autoscale_view()

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py:280, in Collection.get_datalim(self, transData)
    277     return transforms.Bbox.null()
    279 if not transform.is_affine:
--> 280     paths = [transform.transform_path_non_affine(p) for p in paths]
    281     # Don't convert transform to transform.get_affine() here because
    282     # we may have transform.contains_branch(transData) but not
    283     # transforms.get_affine().contains_branch(transData).  But later,
    284     # be careful to only apply the affine part that remains.
    286 if any(transform.contains_branch_seperately(transData)):

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py:280, in <listcomp>(.0)
    277     return transforms.Bbox.null()
    279 if not transform.is_affine:
--> 280     paths = [transform.transform_path_non_affine(p) for p in paths]
    281     # Don't convert transform to transform.get_affine() here because
    282     # we may have transform.contains_branch(transData) but not
    283     # transforms.get_affine().contains_branch(transData).  But later,
    284     # be careful to only apply the affine part that remains.
    286 if any(transform.contains_branch_seperately(transData)):

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/transforms.py:2436, in CompositeGenericTransform.transform_path_non_affine(self, path)
   2434     return path
   2435 elif not self._a.is_affine and self._b.is_affine:
-> 2436     return self._a.transform_path_non_affine(path)
   2437 else:
   2438     return self._b.transform_path_non_affine(
   2439                             self._a.transform_path(path))

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py:190, in InterProjectionTransform.transform_path_non_affine(self, src_path)
    186 geoms = cpatch.path_to_geos(src_path,
    187                             getattr(self, 'force_path_ccw', False))
    189 for geom in geoms:
--> 190     proj_geom = self.target_projection.project_geometry(
    191         geom, self.source_projection)
    192     transformed_geoms.append(proj_geom)
    194 if not transformed_geoms:

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py:805, in Projection.project_geometry(self, geometry, src_crs)
    803 if not method_name:
    804     raise ValueError(f'Unsupported geometry type {geom_type!r}')
--> 805 return getattr(self, method_name)(geometry, src_crs)

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py:948, in Projection._project_polygon(self, polygon, src_crs)
    946 multi_lines = []
    947 for src_ring in [polygon.exterior] + list(polygon.interiors):
--> 948     p_rings, p_mline = self._project_linear_ring(src_ring, src_crs)
    949     if p_rings:
    950         rings.extend(p_rings)

File ~/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py:824, in Projection._project_linear_ring(self, linear_ring, src_crs)
    819 debug = False
    820 # 1) Resolve the initial lines into projected segments
    821 # 1abc
    822 # def23ghi
    823 # jkl41
--> 824 multi_line_string = cartopy.trace.project_linear(linear_ring,
    825                                                  src_crs, self)
    827 # Threshold for whether a point is close enough to be the same
    828 # point as another.
    829 threshold = max(np.abs(self.x_limits + self.y_limits)) * 1e-5

File lib/cartopy/trace.pyx:628, in cartopy.trace.project_linear()

File lib/cartopy/trace.pyx:100, in cartopy.trace.geos_from_shapely()

TypeError: an integer is required

Exception in Tkinter callback
Traceback (most recent call last):
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/tkinter/__init__.py", line 839, in callit
    func(*args)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/backends/_backend_tk.py", line 252, in idle_draw
    self.draw()
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/backends/backend_tkagg.py", line 9, in draw
    super().draw()
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py", line 436, in draw
    self.figure.draw(self.renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 74, in draw_wrapper
    result = draw(artist, renderer, *args, **kwargs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/figure.py", line 2845, in draw
    mimage._draw_list_compositing_images(
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py", line 558, in draw
    return matplotlib.axes.Axes.draw(self, renderer=renderer, **kwargs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 3091, in draw
    mimage._draw_list_compositing_images(
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 990, in draw
    super().draw(renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 366, in draw
    transform, transOffset, offsets, paths = self._prepare_points()
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 343, in _prepare_points
    paths = [transform.transform_path_non_affine(path)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 343, in <listcomp>
    paths = [transform.transform_path_non_affine(path)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/transforms.py", line 2436, in transform_path_non_affine
    return self._a.transform_path_non_affine(path)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py", line 190, in transform_path_non_affine
    proj_geom = self.target_projection.project_geometry(
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py", line 805, in project_geometry
    return getattr(self, method_name)(geometry, src_crs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py", line 948, in _project_polygon
    p_rings, p_mline = self._project_linear_ring(src_ring, src_crs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py", line 824, in _project_linear_ring
    multi_line_string = cartopy.trace.project_linear(linear_ring,
  File "lib/cartopy/trace.pyx", line 628, in cartopy.trace.project_linear
  File "lib/cartopy/trace.pyx", line 100, in cartopy.trace.geos_from_shapely
TypeError: an integer is required
Exception in Tkinter callback
Traceback (most recent call last):
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/tkinter/__init__.py", line 839, in callit
    func(*args)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/backends/_backend_tk.py", line 252, in idle_draw
    self.draw()
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/backends/backend_tkagg.py", line 9, in draw
    super().draw()
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py", line 436, in draw
    self.figure.draw(self.renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 74, in draw_wrapper
    result = draw(artist, renderer, *args, **kwargs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/figure.py", line 2845, in draw
    mimage._draw_list_compositing_images(
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py", line 558, in draw
    return matplotlib.axes.Axes.draw(self, renderer=renderer, **kwargs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 3091, in draw
    mimage._draw_list_compositing_images(
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 990, in draw
    super().draw(renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/artist.py", line 51, in draw_wrapper
    return draw(artist, renderer)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 366, in draw
    transform, transOffset, offsets, paths = self._prepare_points()
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 343, in _prepare_points
    paths = [transform.transform_path_non_affine(path)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/collections.py", line 343, in <listcomp>
    paths = [transform.transform_path_non_affine(path)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/matplotlib/transforms.py", line 2436, in transform_path_non_affine
    return self._a.transform_path_non_affine(path)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/mpl/geoaxes.py", line 190, in transform_path_non_affine
    proj_geom = self.target_projection.project_geometry(
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py", line 805, in project_geometry
    return getattr(self, method_name)(geometry, src_crs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py", line 948, in _project_polygon
    p_rings, p_mline = self._project_linear_ring(src_ring, src_crs)
  File "/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/cartopy/crs.py", line 824, in _project_linear_ring
    multi_line_string = cartopy.trace.project_linear(linear_ring,
  File "lib/cartopy/trace.pyx", line 628, in cartopy.trace.project_linear
  File "lib/cartopy/trace.pyx", line 100, in cartopy.trace.geos_from_shapely
TypeError: an integer is required

Anything else we need to know?

No response

Environment

/home/andrew/miniconda3/envs/AQUATIC/lib/python3.10/site-packages/_distutils_hack/init.py:33: UserWarning: Setuptools is replacing distutils.
warnings.warn("Setuptools is replacing distutils.")

INSTALLED VERSIONS

commit: None
python: 3.10.5 | packaged by conda-forge | (main, Jun 14 2022, 07:04:59) [GCC 10.3.0]
python-bits: 64
OS: Linux
OS-release: 5.4.0-122-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: ('en_US', 'UTF-8')
libhdf5: 1.12.2
libnetcdf: 4.8.1

xarray: 2022.6.0
pandas: 1.4.3
numpy: 1.23.2
scipy: 1.9.0
netCDF4: 1.6.0
pydap: None
h5netcdf: None
h5py: None
Nio: None
zarr: None
cftime: 1.6.1
nc_time_axis: None
PseudoNetCDF: None
rasterio: None
cfgrib: None
iris: None
bottleneck: None
dask: 2022.8.0
distributed: 2022.8.0
matplotlib: 3.5.3
cartopy: 0.20.3
seaborn: 0.11.2
numbagg: None
fsspec: 2022.7.1
cupy: None
pint: None
sparse: None
flox: None
numpy_groupies: None
setuptools: 65.0.2
pip: 22.2.2
conda: None
pytest: None
IPython: 8.4.0
sphinx: None

@arfriedman arfriedman added bug needs triage Issue that has not been reviewed by xarray team member labels Aug 17, 2022
@keewis
Copy link
Collaborator

keewis commented Aug 18, 2022

this seems to be a compatibility issue between cartopy and shapely=1.8.3, see SciTools/cartopy#2067. Installing shapely!=1.8.3 should avoid the TypeError for now.

closing since we can't really do anything about this.

@keewis keewis closed this as completed Aug 18, 2022
@keewis keewis added upstream issue and removed needs triage Issue that has not been reviewed by xarray team member bug labels Aug 18, 2022
@arfriedman
Copy link
Contributor Author

Thank you. It also now works with shapely 1.8.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants