When trying to plot a 2D array in cartopy projected axes using contourf, I am receiving a TopologicalError. This is the code:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import numpy as np
from shapely.geos import TopologicalError
data = np.array(
[[ 8, 10, 2, 5, 3, 6, 5, 3, 0, 0, 0, 0, 0, 0, 0],
[ 7, 5, 3, 6, 5, 4, 2, 1, 1, 0, 0, 0, 0, 0, 0],
[ 8, 10, 2, 7, 1, 2, 1, 0, 0, 1, 0, 0, 0, 0, 0],
[14, 8, 12, 9, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[15, 8, 10, 5, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 7, 7, 9, 5, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[ 4, 5, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 2, 4, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
])
x = np.array([-9.05365, -9.05266, -9.05167, -9.05068, -9.04969,
-9.0487, -9.04771, -9.04672, -9.04573, -9.04474,
-9.04375, -9.04276, -9.04177, -9.04078, -9.03979])
y = np.array([53.2024, 53.203, 53.2036, 53.2042, 53.2048,
53.2054, 53.206, 53.2065, 53.2071, 53.2077])
data = np.ma.masked_where(data==0, data)
ax = plt.axes(projection=ccrs.Mercator(central_longitude=-9))
try:
ax.contourf(x, y, data, transform=ccrs.PlateCarree())
except TopologicalError as exc:
pass # Do something to get the conflicting location (x, y)
When running this code, I am getting the TopologyException
message below, followed by a rather long traceback (see below). The TopologyException
is:
TopologyException: side location conflict at -9.0506799999999998 53.206000000000003
Now, under the except
block, I would like to fix the array in the location indicated by the TopologyException
(-9.0506799999999998 53.206000000000003
), and try to plot it again. I would use a while
loop to fix the array as many times as needed, retrieving the conflicting location and fixing the array at that location. I have to repeat this procedure for many other arrays like this.
Even though the message is displayed in the screen, I don't know how to get the location -9.0506799999999998 53.206000000000003 from the script, since I can't find it in exc
. I would be very grateful if somebody could explain how to get those numbers as new variables lon
and lat
.
This error can be avoided if not using a masked array, but I am masking the 0's because I don't want to plot them.
Below is the traceback. Many thanks.
TopologyException: side location conflict at -9.0506799999999998 53.206000000000003
TopologyException: side location conflict at -9.0506799999999998 53.206000000000003
Error in callback <function install_repl_displayhook.<locals>.post_execute at 0x00000204E9F74280> (for post_execute):
Traceback (most recent call last):
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\predicates.py", line 15, in __call__
return self.fn(this._geom, other._geom, *args)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\geos.py", line 584, in errcheck_predicate
raise PredicateError("Failed to evaluate %s" % repr(func))
PredicateError: Failed to evaluate <_FuncPtr object at 0x00000204EB13ED40>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\pyplot.py", line 139, in post_execute
draw_all()
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\_pylab_helpers.py", line 137, in draw_all
manager.canvas.draw_idle()
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\backend_bases.py", line 2055, in draw_idle
self.draw(*args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\backends\backend_agg.py", line 406, in draw
self.figure.draw(self.renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 74, in draw_wrapper
result = draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\figure.py", line 2790, in draw
mimage._draw_list_compositing_images(
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\image.py", line 132, in _draw_list_compositing_images
a.draw(renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\cartopy\mpl\geoaxes.py", line 558, in draw
return matplotlib.axes.Axes.draw(self, renderer=renderer, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\_api\deprecation.py", line 431, in wrapper
return func(*inner_args, **inner_kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\axes\_base.py", line 2921, in draw
mimage._draw_list_compositing_images(renderer, self, artists)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\image.py", line 132, in _draw_list_compositing_images
a.draw(renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 1012, in draw
super().draw(renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 352, in draw
transform, transOffset, offsets, paths = self._prepare_points()
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 329, in _prepare_points
paths = [transform.transform_path_non_affine(path)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 329, in <listcomp>
paths = [transform.transform_path_non_affine(path)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\transforms.py", line 2396, in transform_path_non_affine
return self._a.transform_path_non_affine(path)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\cartopy\mpl\geoaxes.py", line 186, in transform_path_non_affine
geoms = cpatch.path_to_geos(src_path,
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\cartopy\mpl\patch.py", line 178, in path_to_geos
collection[-1][0].contains(geom.exterior)):
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\geometry\base.py", line 747, in contains
return bool(self.impl['contains'](self, other))
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\predicates.py", line 18, in __call__
self._check_topology(err, this, other)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\topology.py", line 35, in _check_topology
raise TopologicalError(
TopologicalError: The operation 'GEOSContains_r' could not be performed. Likely cause is invalidity of the geometry <shapely.geometry.polygon.Polygon object at 0x000002048290D820>
TopologyException: side location conflict at -9.0506799999999998 53.206000000000003
Traceback (most recent call last):
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\predicates.py", line 15, in __call__
return self.fn(this._geom, other._geom, *args)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\geos.py", line 584, in errcheck_predicate
raise PredicateError("Failed to evaluate %s" % repr(func))
PredicateError: Failed to evaluate <_FuncPtr object at 0x00000204EB13ED40>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\IPython\core\formatters.py", line 341, in __call__
return printer(obj)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\IPython\core\pylabtools.py", line 253, in <lambda>
png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\IPython\core\pylabtools.py", line 137, in print_figure
fig.canvas.print_figure(bytes_io, **kw)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\backend_bases.py", line 2230, in print_figure
self.figure.draw(renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 74, in draw_wrapper
result = draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\figure.py", line 2790, in draw
mimage._draw_list_compositing_images(
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\image.py", line 132, in _draw_list_compositing_images
a.draw(renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\cartopy\mpl\geoaxes.py", line 558, in draw
return matplotlib.axes.Axes.draw(self, renderer=renderer, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\_api\deprecation.py", line 431, in wrapper
return func(*inner_args, **inner_kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\axes\_base.py", line 2921, in draw
mimage._draw_list_compositing_images(renderer, self, artists)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\image.py", line 132, in _draw_list_compositing_images
a.draw(renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 1012, in draw
super().draw(renderer)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\artist.py", line 51, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 352, in draw
transform, transOffset, offsets, paths = self._prepare_points()
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 329, in _prepare_points
paths = [transform.transform_path_non_affine(path)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\collections.py", line 329, in <listcomp>
paths = [transform.transform_path_non_affine(path)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\matplotlib\transforms.py", line 2396, in transform_path_non_affine
return self._a.transform_path_non_affine(path)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\cartopy\mpl\geoaxes.py", line 186, in transform_path_non_affine
geoms = cpatch.path_to_geos(src_path,
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\cartopy\mpl\patch.py", line 178, in path_to_geos
collection[-1][0].contains(geom.exterior)):
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\geometry\base.py", line 747, in contains
return bool(self.impl['contains'](self, other))
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\predicates.py", line 18, in __call__
self._check_topology(err, this, other)
File "C:\Users\dpereiro\Miniconda3\envs\opendrift\lib\site-packages\shapely\topology.py", line 35, in _check_topology
raise TopologicalError(
TopologicalError: The operation 'GEOSContains_r' could not be performed. Likely cause is invalidity of the geometry <shapely.geometry.polygon.Polygon object at 0x00000204E87FDD90>
<Figure size 432x288 with 1 Axes>