Closed rabernat closed 4 years ago
Right now, datashader itself has no support for rectilinear meshes, and as you say the HoloViews trick of using Trimeshes via QuadMesh is not nearly as efficient as it could be. Supporting rectilinear meshes seems very feasible, and it may be relevant to a project we're working on, so I hope we will be able to address it relatively soon. But unfortunately this isn't something that we've already agreed and scheduled, so I can't predict precisely when it would come up next in priority.
Update: We are hoping to get funding soon to add native quadmesh support, which should be closer in speed to the regularly spaced raster regridding than to the current slower trimesh-based approximation. So it's likely to be funded in 2018, but I cannot promise any particular date. We'll also be improving the trimesh speed at the same time, and adding dask support for both cases.
Added in https://github.com/holoviz/datashader/pull/885 and available for testing via conda install -c pyviz/label/dev datashader=0.11.0a2
I recently tried this again, assuming it had been fixed in the latest releases. I'm using holoviews version 1.13.3, and datashader version 0.10.0. Here is a MRE:
import hvplot.xarray
import holoviews as hv
from holoviews.operation.datashader import datashade
import xarray as xr
import numpy as np
da = xr.DataArray(np.random.rand(1000, 2000), dims=['y', 'x'], name='foo',
coords={'x': (['x'], np.arange(2000)),
'y': (['y'], np.arange(1000)**0.5)})
da = da.chunk() #use dask
hv_ds = hv.Dataset(da)
qm = hv_ds.to(hv.QuadMesh, kdims=["x", "y"], dynamic=True)
datashade(qm)
This raises the following error
WARNING:param.QuadMesh01455: Setting non-parameter attribute dynamic=True using a mechanism intended only for parameters
WARNING:param.dynamic_operation: Callable raised "TypingError('Failed in nopython mode pipeline (step: nopython frontend)\n\x1b[1m\x1b[1mnon-precise type pyobject\x1b[0m\n\x1b[0m\x1b[1mDuring: typing of argument at <extend_cpu> (4)\x1b[0m\n\x1b[1m\nFile "<extend_cpu>", line 4:\x1b[0m\n\x1b[1m<source missing, REPL/exec in use?>\x1b[0m\n\nThis error may have been caused by the following argument(s):\n- argument 4: \x1b[1mcannot determine Numba type of <class \'dask.array.core.Array\'>\x1b[0m\n')".
Invoked as dynamic_operation(height=400, scale=1.0, width=400, x_range=None, y_range=None)
---------------------------------------------------------------------------
TypingError Traceback (most recent call last)
/srv/conda/envs/notebook/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:
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/dimension.py in _repr_mimebundle_(self, include, exclude)
1310 combined and returned.
1311 """
-> 1312 return Store.render(self)
1313
1314
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/options.py in render(cls, obj)
1393 data, metadata = {}, {}
1394 for hook in hooks:
-> 1395 ret = hook(obj)
1396 if ret is None:
1397 continue
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj)
280 if not ip.display_formatter.formatters['text/plain'].pprint:
281 return None
--> 282 return display(obj, raw_output=True)
283
284
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw_output, **kwargs)
256 elif isinstance(obj, (HoloMap, DynamicMap)):
257 with option_state(obj):
--> 258 output = map_display(obj)
259 elif isinstance(obj, Plot):
260 output = render(obj)
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in wrapped(element)
144 try:
145 max_frames = OutputSettings.options['max_frames']
--> 146 mimebundle = fn(element, max_frames=max_frames)
147 if mimebundle is None:
148 return {}, {}
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/ipython/display_hooks.py in map_display(vmap, max_frames)
204 return None
205
--> 206 return render(vmap)
207
208
/srv/conda/envs/notebook/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
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/plotting/renderer.py in components(self, obj, fmt, comm, **kwargs)
386 doc = Document()
387 with config.set(embed=embed):
--> 388 model = plot.layout._render_model(doc, comm)
389 if embed:
390 return render_model(model, comm)
/srv/conda/envs/notebook/lib/python3.7/site-packages/panel/viewable.py in _render_model(self, doc, comm)
416 if comm is None:
417 comm = state._comm_manager.get_server_comm()
--> 418 model = self.get_root(doc, comm)
419
420 if config.embed:
/srv/conda/envs/notebook/lib/python3.7/site-packages/panel/viewable.py in get_root(self, doc, comm)
645 """
646 doc = doc or _curdoc()
--> 647 root = self._get_model(doc, comm=comm)
648 self._preprocess(root)
649 ref = root.ref['id']
/srv/conda/envs/notebook/lib/python3.7/site-packages/panel/layout.py in _get_model(self, doc, root, parent, comm)
118 if root is None:
119 root = model
--> 120 objects = self._get_objects(model, [], doc, root, comm)
121 props = dict(self._init_properties(), objects=objects)
122 model.update(**self._process_param_change(props))
/srv/conda/envs/notebook/lib/python3.7/site-packages/panel/layout.py in _get_objects(self, model, old_objects, doc, root, comm)
108 else:
109 try:
--> 110 child = pane._get_model(doc, root, model, comm)
111 except RerenderError:
112 return self._get_objects(model, current_objects[:i], doc, root, comm)
/srv/conda/envs/notebook/lib/python3.7/site-packages/panel/pane/holoviews.py in _get_model(self, doc, root, parent, comm)
225 plot = self.object
226 else:
--> 227 plot = self._render(doc, comm, root)
228
229 plot.pane = self
/srv/conda/envs/notebook/lib/python3.7/site-packages/panel/pane/holoviews.py in _render(self, doc, comm, root)
284 kwargs = {}
285
--> 286 return renderer.get_plot(self.object, **kwargs)
287
288 def _cleanup(self, root):
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/plotting/bokeh/renderer.py in get_plot(self_or_cls, obj, doc, renderer, **kwargs)
71 combining the bokeh model with another plot.
72 """
---> 73 plot = super(BokehRenderer, self_or_cls).get_plot(obj, doc, renderer, **kwargs)
74 if plot.document is None:
75 plot.document = Document() if self_or_cls.notebook_context else curdoc()
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
214
215 # Initialize DynamicMaps with first data item
--> 216 initialize_dynamic(obj)
217
218 if not renderer:
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/plotting/util.py in initialize_dynamic(obj)
249 continue
250 if not len(dmap):
--> 251 dmap[dmap._initial_key()]
252
253
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/spaces.py in __getitem__(self, key)
1285 # Not a cross product and nothing cached so compute element.
1286 if cache is not None: return cache
-> 1287 val = self._execute_callback(*tuple_key)
1288 if data_slice:
1289 val = self._dataslice(val, data_slice)
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/spaces.py in _execute_callback(self, *args)
1059
1060 with dynamicmap_memoization(self.callback, self.streams):
-> 1061 retval = self.callback(*args, **kwargs)
1062 return self._style(retval)
1063
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/spaces.py in __call__(self, *args, **kwargs)
693
694 try:
--> 695 ret = self.callable(*args, **kwargs)
696 except KeyError:
697 # KeyError is caught separately because it is used to signal
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/util/__init__.py in dynamic_operation(*key, **kwargs)
1008 def dynamic_operation(*key, **kwargs):
1009 key, obj = resolve(key, kwargs)
-> 1010 return apply(obj, *key, **kwargs)
1011
1012 operation = self.p.operation
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/util/__init__.py in apply(element, *key, **kwargs)
1000 def apply(element, *key, **kwargs):
1001 kwargs = dict(util.resolve_dependent_kwargs(self.p.kwargs), **kwargs)
-> 1002 processed = self._process(element, key, kwargs)
1003 if (self.p.link_dataset and isinstance(element, Dataset) and
1004 isinstance(processed, Dataset) and processed._dataset is None):
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/util/__init__.py in _process(self, element, key, kwargs)
982 elif isinstance(self.p.operation, Operation):
983 kwargs = {k: v for k, v in kwargs.items() if k in self.p.operation.param}
--> 984 return self.p.operation.process_element(element, key, **kwargs)
985 else:
986 return self.p.operation(element, **kwargs)
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/operation.py in process_element(self, element, key, **params)
172 self.p = param.ParamOverrides(self, params,
173 allow_extra_keywords=self._allow_extra_keywords)
--> 174 return self._apply(element, key)
175
176
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/operation.py in _apply(self, element, key)
130
131 element_pipeline = getattr(element, '_pipeline', None)
--> 132 ret = self._process(element, key)
133
134 for hook in self._postprocess_hooks:
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/operation/datashader.py in _process(self, element, key)
1442
1443 def _process(self, element, key=None):
-> 1444 agg = rasterize._process(self, element, key)
1445 shaded = shade._process(self, agg, key)
1446 return shaded
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/operation/datashader.py in _process(self, element, key)
1421 if k in transform.param})
1422 op._precomputed = self._precomputed
-> 1423 element = element.map(op, predicate)
1424 self._precomputed = op._precomputed
1425
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/data/__init__.py in pipelined_fn(*args, **kwargs)
214
215 try:
--> 216 result = method_fn(*args, **kwargs)
217
218 op = method_op.instance(
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/data/__init__.py in map(self, *args, **kwargs)
1181
1182 def map(self, *args, **kwargs):
-> 1183 return super(Dataset, self).map(*args, **kwargs)
1184 map.__doc__ = LabelledData.map.__doc__
1185
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/dimension.py in map(self, map_fn, specs, clone)
703 return deep_mapped
704 else:
--> 705 return map_fn(self) if applies else self
706
707
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/operation.py in __call__(self, element, **kwargs)
192 elif ((self._per_element and isinstance(element, Element)) or
193 (not self._per_element and isinstance(element, ViewableElement))):
--> 194 return self._apply(element)
195 elif 'streams' not in kwargs:
196 kwargs['streams'] = self.p.streams
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/core/operation.py in _apply(self, element, key)
130
131 element_pipeline = getattr(element, '_pipeline', None)
--> 132 ret = self._process(element, key)
133
134 for hook in self._postprocess_hooks:
/srv/conda/envs/notebook/lib/python3.7/site-packages/holoviews/operation/datashader.py in _process(self, element, key)
1089
1090 vdim = getattr(agg_fn, 'column', element.vdims[0].name)
-> 1091 agg = cvs.quadmesh(data[vdim], x.name, y.name, agg_fn)
1092 xdim, ydim = list(agg.dims)[:2][::-1]
1093 if xtype == "datetime":
/srv/conda/envs/notebook/lib/python3.7/site-packages/datashader/core.py in quadmesh(self, source, x, y, agg)
770 dims=list(xarr.dims)))
771
--> 772 return bypixel(source, self, glyph, agg)
773
774 # TODO re 'untested', below: Consider replacing with e.g. a 3x3
/srv/conda/envs/notebook/lib/python3.7/site-packages/datashader/core.py in bypixel(source, canvas, glyph, agg)
1159 with np.warnings.catch_warnings():
1160 np.warnings.filterwarnings('ignore', r'All-NaN (slice|axis) encountered')
-> 1161 return bypixel.pipeline(source, schema, canvas, glyph, agg)
1162
1163
/srv/conda/envs/notebook/lib/python3.7/site-packages/datashader/utils.py in __call__(self, head, *rest, **kwargs)
91 typ = type(head)
92 if typ in lk:
---> 93 return lk[typ](head, *rest, **kwargs)
94 for cls in getmro(typ)[1:]:
95 if cls in lk:
/srv/conda/envs/notebook/lib/python3.7/site-packages/datashader/data_libraries/xarray.py in xarray_pipeline(df, schema, canvas, glyph, summary)
17 def xarray_pipeline(df, schema, canvas, glyph, summary):
18 cuda = cupy and isinstance(df[glyph.name].data, cupy.ndarray)
---> 19 return glyph_dispatch(glyph, df, schema, canvas, summary, cuda)
20
21
/srv/conda/envs/notebook/lib/python3.7/site-packages/datashader/utils.py in __call__(self, head, *rest, **kwargs)
94 for cls in getmro(typ)[1:]:
95 if cls in lk:
---> 96 return lk[cls](head, *rest, **kwargs)
97 raise TypeError("No dispatch for {0} type".format(typ))
98
/srv/conda/envs/notebook/lib/python3.7/site-packages/datashader/data_libraries/pandas.py in default(glyph, source, schema, canvas, summary, cuda)
43
44 bases = create((height, width))
---> 45 extend(bases, source, x_st + y_st, x_range + y_range)
46
47 return finalize(bases,
/srv/conda/envs/notebook/lib/python3.7/site-packages/datashader/glyphs/quadmesh.py in extend(aggs, xr_ds, vt, bounds)
186 do_extend = extend_cpu
187
--> 188 do_extend(xs, ys, *aggs_and_cols)
189
190 return extend
/srv/conda/envs/notebook/lib/python3.7/site-packages/numba/core/dispatcher.py in _compile_for_args(self, *args, **kws)
413 e.patch_message(msg)
414
--> 415 error_rewrite(e, 'typing')
416 except errors.UnsupportedError as e:
417 # Something unsupported is present in the user code, add help info
/srv/conda/envs/notebook/lib/python3.7/site-packages/numba/core/dispatcher.py in error_rewrite(e, issue_type)
356 raise e
357 else:
--> 358 reraise(type(e), e, None)
359
360 argtypes = []
/srv/conda/envs/notebook/lib/python3.7/site-packages/numba/core/utils.py in reraise(tp, value, tb)
78 value = tp()
79 if value.__traceback__ is not tb:
---> 80 raise value.with_traceback(tb)
81 raise value
82
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
non-precise type pyobject
During: typing of argument at <extend_cpu> (4)
File "<extend_cpu>", line 4:
<source missing, REPL/exec in use?>
This error may have been caused by the following argument(s):
- argument 4: cannot determine Numba type of <class 'dask.array.core.Array'>
Am I mistaken in assuming this should work with dask?
Can you try upgrading to Datashader 0.11 where this was fixed? There's been some annoying regressions in numba 0.49 and 0.50 which may have prevented you from auto-upgrading because Datashader pinned older versions.
Description
I normally use datashader via holoviews in the following way.
where
ds
is a very big xarray dataset.I am converting to
QuadMesh
rather thanImage
because the grid spacing of my dataset is irregular. Specifically, in VTK speak, it is rectilinear mesh:Shading the
QuadMesh
is extremely slow compared toImage
. My understanding is that theQuadMesh
is first internally converted toTriMesh
by datashader. It should be possible to have a much more optimized path for rectilinear meshes, because of their inherent structure.Your environment
cc @philippjfr