geoviews
geoviews copied to clipboard
Plotting fails when using a non-global projection for rasterised projected mesh
import holoviews as hv
import geoviews as gv
import cmocean
import matplotlib.pyplot as plt
from holoviews import opts
from holoviews.operation.datashader import datashade, shade, dynspread, rasterize
from holoviews.operation import decimate
import numpy as np
import xarray as xr
import cartopy.crs as ccrs
hv.extension('bokeh')
hv.__version__, gv.__version__, xr.__version__
('1.12.3', '1.6.2', '0.11.3')
# WARNING: Broken if you use a non-global projection.
greenland_projection = ccrs.Miller()
projected_trimesh = gv.project(trimesh, projection=greenland_projection)
projected_fesom_mesh = gv.project(fesom_mesh, projection=greenland_projection)
# This next line results in an index error if a different projection is used:
rasterize(projected_trimesh).opts(
colorbar=True, tools=['hover'],
clim=(-2, 5), color_levels = [-2, -1.5, -1, -0.5, -0.25, 0.25, 0.5, 1, 1.5, 2],
width=600, projection=greenland_projection, data_aspect=1,
cmap=cmocean.cm.thermal)
Some discussion with @philippjfr seems to reveal that the gv.project command has problems when displaying plots where some of the simplifies are no longer on the map:
That confirms my guess I think, I think the project_trimesh operation isn't correctly dropping simplices which reference vertices outside of the projection so when it comes to plotting it tries to look for vertices which no longer exist.
Here is a full traceback of such an error (e.g. when using ccrs.EuroPP:
WARNING:param.dynamic_operation: Callable raised "IndexError('index 103130 is out of bounds for size 103130')".
Invoked as dynamic_operation(height=400, scale=1.0, width=400, x_range=None, y_range=None)
WARNING:param.dynamic_operation: Callable raised "IndexError('index 103130 is out of bounds for size 103130')".
Invoked as dynamic_operation(height=400, scale=1.0, width=400, x_range=None, y_range=None)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude)
968
969 if method is not None:
--> 970 return method(include=include, exclude=exclude)
971 return None
972 else:
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/dimension.py in _repr_mimebundle_(self, include, exclude)
1291 combined and returned.
1292 """
-> 1293 return Store.render(self)
1294
1295
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/options.py in render(cls, obj)
1360 data, metadata = {}, {}
1361 for hook in hooks:
-> 1362 ret = hook(obj)
1363 if ret is None:
1364 continue
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj)
278 if not ip.display_formatter.formatters['text/plain'].pprint:
279 return None
--> 280 return display(obj, raw_output=True)
281
282
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw_output, **kwargs)
254 elif isinstance(obj, (HoloMap, DynamicMap)):
255 with option_state(obj):
--> 256 output = map_display(obj)
257 elif isinstance(obj, Plot):
258 output = render(obj)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in wrapped(element)
143 try:
144 max_frames = OutputSettings.options['max_frames']
--> 145 mimebundle = fn(element, max_frames=max_frames)
146 if mimebundle is None:
147 return {}, {}
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in map_display(vmap, max_frames)
203 return None
204
--> 205 return render(vmap)
206
207
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in render(obj, **kwargs)
66 renderer = renderer.instance(fig='png')
67
---> 68 return renderer.components(obj, **kwargs)
69
70
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/plotting/bokeh/renderer.py in components(self, obj, fmt, comm, **kwargs)
248 # Bokeh has to handle comms directly in <0.12.15
249 comm = False if bokeh_version < '0.12.15' else comm
--> 250 return super(BokehRenderer, self).components(obj,fmt, comm, **kwargs)
251
252
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/plotting/renderer.py in components(self, obj, fmt, comm, **kwargs)
319 plot = obj
320 else:
--> 321 plot, fmt = self._validate(obj, fmt)
322
323 data, metadata = {}, {}
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/plotting/renderer.py in _validate(self, obj, fmt, **kwargs)
218 if isinstance(obj, tuple(self.widgets.values())):
219 return obj, 'html'
--> 220 plot = self.get_plot(obj, renderer=self, **kwargs)
221
222 fig_formats = self.mode_formats['fig'][self.mode]
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/plotting/bokeh/renderer.py in get_plot(self_or_cls, obj, doc, renderer, **kwargs)
133 curdoc().theme = self_or_cls.theme
134 doc.theme = self_or_cls.theme
--> 135 plot = super(BokehRenderer, self_or_cls).get_plot(obj, renderer, **kwargs)
136 plot.document = doc
137 return plot
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, renderer, **kwargs)
184
185 # Initialize DynamicMaps with first data item
--> 186 initialize_dynamic(obj)
187
188 if not isinstance(obj, Plot):
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/plotting/util.py in initialize_dynamic(obj)
248 continue
249 if not len(dmap):
--> 250 dmap[dmap._initial_key()]
251
252
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/spaces.py in __getitem__(self, key)
1323 # Not a cross product and nothing cached so compute element.
1324 if cache is not None: return cache
-> 1325 val = self._execute_callback(*tuple_key)
1326 if data_slice:
1327 val = self._dataslice(val, data_slice)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/spaces.py in _execute_callback(self, *args)
1096
1097 with dynamicmap_memoization(self.callback, self.streams):
-> 1098 retval = self.callback(*args, **kwargs)
1099 return self._style(retval)
1100
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/spaces.py in __call__(self, *args, **kwargs)
731
732 try:
--> 733 ret = self.callable(*args, **kwargs)
734 except KeyError:
735 # KeyError is caught separately because it is used to signal
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/util/__init__.py in dynamic_operation(*key, **kwargs)
934 if map_obj._posarg_keys and not key:
935 key = tuple(kwargs[k] for k in map_obj._posarg_keys)
--> 936 return self._process(map_obj[key], key, kwargs)
937 if isinstance(self.p.operation, Operation):
938 return OperationCallable(dynamic_operation, inputs=[map_obj],
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/spaces.py in __getitem__(self, key)
1323 # Not a cross product and nothing cached so compute element.
1324 if cache is not None: return cache
-> 1325 val = self._execute_callback(*tuple_key)
1326 if data_slice:
1327 val = self._dataslice(val, data_slice)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/spaces.py in _execute_callback(self, *args)
1096
1097 with dynamicmap_memoization(self.callback, self.streams):
-> 1098 retval = self.callback(*args, **kwargs)
1099 return self._style(retval)
1100
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/spaces.py in __call__(self, *args, **kwargs)
731
732 try:
--> 733 ret = self.callable(*args, **kwargs)
734 except KeyError:
735 # KeyError is caught separately because it is used to signal
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/util/__init__.py in dynamic_operation(*key, **kwargs)
928 kwargs = dict(self._eval_kwargs(), **kwargs)
929 obj = map_obj[key] if isinstance(map_obj, HoloMap) else map_obj
--> 930 return self._process(obj, key, kwargs)
931 else:
932 def dynamic_operation(*key, **kwargs):
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/util/__init__.py in _process(self, element, key, kwargs)
906 kwargs = {k: v for k, v in kwargs.items()
907 if k in self.p.operation.params()}
--> 908 return self.p.operation.process_element(element, key, **kwargs)
909 else:
910 return self.p.operation(element, **kwargs)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/operation.py in process_element(self, element, key, **params)
141 """
142 self.p = param.ParamOverrides(self, params)
--> 143 return self._apply(element, key)
144
145
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/operation.py in _apply(self, element, key)
119 for hook in self._preprocess_hooks:
120 kwargs.update(hook(self, element))
--> 121 ret = self._process(element, key)
122 for hook in self._postprocess_hooks:
123 ret = hook(self, ret, **kwargs)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/operation/datashader.py in _process(self, element, key)
855 op = transform.instance(**op_params)
856 op._precomputed = self._precomputed
--> 857 element = element.map(op, predicate)
858 self._precomputed = op._precomputed
859 return element
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/dimension.py in map(self, map_fn, specs, clone)
701 return deep_mapped
702 else:
--> 703 return map_fn(self) if applies else self
704
705
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/operation.py in __call__(self, element, **kwargs)
159 for k, el in element.items()])
160 elif isinstance(element, ViewableElement):
--> 161 return self._apply(element)
162 elif 'streams' not in kwargs:
163 kwargs['streams'] = self.p.streams
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/core/operation.py in _apply(self, element, key)
119 for hook in self._preprocess_hooks:
120 kwargs.update(hook(self, element))
--> 121 ret = self._process(element, key)
122 for hook in self._postprocess_hooks:
123 ret = hook(self, ret, **kwargs)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/operation/datashader.py in _process(self, element, key)
757 precomputed = self._precompute_wireframe(element, agg)
758 else:
--> 759 precomputed = self._precompute(element, agg)
760
761 params = dict(get_param_values(element), kdims=[x, y],
~/anaconda3/envs/palmod/lib/python3.7/site-packages/holoviews/operation/datashader.py in _precompute(self, element, agg)
700 if dtype.kind != 'i':
701 simplices[c] = simplices[c].astype('int')
--> 702 return {'mesh': mesh(verts, simplices), 'simplices': simplices,
703 'vertices': verts}
704
~/anaconda3/envs/palmod/lib/python3.7/site-packages/datashader/utils.py in mesh(vertices, simplices)
494 return _dd_mesh(vertices, simplices)
495
--> 496 return _pd_mesh(vertices, simplices)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/datashader/utils.py in _pd_mesh(vertices, simplices)
440 if not vertex_idxs.dtype == 'int64':
441 vertex_idxs = vertex_idxs.astype(np.int64)
--> 442 vals = np.take(vertices.values, vertex_idxs, axis=0)
443 vals = vals.reshape(np.prod(vals.shape[:2]), vals.shape[2])
444 res = pd.DataFrame(vals, columns=vertices.columns)
~/anaconda3/envs/palmod/lib/python3.7/site-packages/numpy/core/fromnumeric.py in take(a, indices, axis, out, mode)
187 [5, 7]])
188 """
--> 189 return _wrapfunc(a, 'take', indices, axis=axis, out=out, mode=mode)
190
191
~/anaconda3/envs/palmod/lib/python3.7/site-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
54 def _wrapfunc(obj, method, *args, **kwds):
55 try:
---> 56 return getattr(obj, method)(*args, **kwds)
57
58 # An AttributeError occurs if the object does not have
IndexError: index 103130 is out of bounds for size 103130