-
-
Notifications
You must be signed in to change notification settings - Fork 403
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
datashader and rasterize=True not updating all layers #5595
Comments
I can reproduce an issue using these versions:
and this code: import hvplot.pandas
import pandas
pandas.options.plotting.backend = "holoviews"
pandas.DataFrame({"a": [ i for i in range( 10_000)],
"b": [ i-2000 for i in range(2, 10_002)]}).plot(datashade=True) * \
pandas.DataFrame({"c": [-i-4000 for i in range(3, 10_003)],
"d": [-i-6000 for i in range(4, 10_004)]}).plot(datashade=True) if I zoom in and out a bit. It works at first, but then hits a datashader error and fails to update one of the traces:
|
Problem identified in datashader as issue holoviz/datashader#1166. |
There is another problem related to import holoviews as hv
import numpy as np
from holoviews.operation.datashader import datashade
hv.extension("bokeh")
data = np.arange(10_000)
p1 = hv.Curve(data)
p2 = hv.Curve(data - 1000)
p3 = hv.Curve(-data)
p4 = hv.Curve(-data - 1000)
o1 = hv.Overlay([p1, p2])
o2 = hv.Overlay([p3, p4])
o = datashade(o1, cmap="blue") * datashade(o2, cmap="red")
nd1 = hv.NdOverlay({"p1": p1, "p2": p2})
nd2 = hv.NdOverlay({"p3": p3, "p4": p4})
nd = datashade(nd1, cmap="blue") * datashade(nd2, cmap="red")
o.opts(title="Overlay == works") + nd.opts(title="NdOverlay != works") |
@hoxbro , I can reproduce that problem as well, but in this case, I don't see any errors in the JS console, so I can't assign the problem to Datashader this time. Is there thus a problem in HoloViews as well? |
I think the problem is in Holoviews. |
After looking into it, it looks to me like the issue is in the My suspicion is that the bug is in how operation callbacks try to merge their streams when overlayed. |
Just reporting some small progress. Inspecting Code to reproduce: import holoviews as hv
import numpy as np
from holoviews.operation.datashader import datashade
import panel as pn
hv.extension("bokeh")
data = np.arange(10_000)
op = datashade
p1 = hv.Curve(data)
p2 = hv.Curve(data - 1000)
p3 = hv.Curve(-data)
p4 = hv.Curve(-data - 1000)
nd1 = hv.NdOverlay({"p1": p1, "p2": p2})
nd2 = hv.NdOverlay({"p3": p3, "p4": p4})
dnd1 = op(nd1, cmap='blue')
dnd2 = op(nd2, cmap='red')
nd = dnd1 * dnd2
hv.render(nd) Diff to apply: diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py
index cba14bb70..999b51deb 100644
--- a/holoviews/plotting/bokeh/element.py
+++ b/holoviews/plotting/bokeh/element.py
@@ -208,6 +208,11 @@ class ElementPlot(BokehPlot, GenericElementPlot):
self.handles = {} if plot is None else self.handles['plot']
self.static = len(self.hmap) == 1 and len(self.keys) == len(self.hmap)
self.callbacks, self.source_streams = self._construct_callbacks()
+ print('element:')
+ print(element)
+ print('source_streams:')
+ print(self.source_streams)
+ print()
self.static_source = False Output: element:
:DynamicMap []
:Overlay
.RGB.I :RGB [x,y] (R,G,B,A)
.RGB.II :RGB [x,y] (R,G,B,A)
source_streams:
[]
element:
:DynamicMap []
:RGB [x,y] (R,G,B,A)
source_streams:
[RangeXY(x_range=None,y_range=None), PlotSize(height=400,scale=1.0,width=400)]
element:
:DynamicMap []
:RGB [x,y] (R,G,B,A)
source_streams:
[] Suspecting this has nothing to do with |
We did some more digging. Running the following script: import holoviews as hv
import numpy as np
from holoviews.operation.datashader import datashade
hv.extension("bokeh")
data = np.arange(10_000)
op = datashade
c1 = hv.Curve(data, label='c1')
c2 = hv.Curve(data - 500, label='c2')
c3 = hv.Curve(data - 1000, label='c3')
c4 = hv.Curve(-data, label='c4')
c5 = hv.Curve(-data - 500, label='c5')
# Build the NDOverlays
nda = hv.NdOverlay({"c1": c1, "c2": c2, "c3": c3}, label='ndA') # 3 curves
ndb = hv.NdOverlay({"c4": c4, "c5": c5}, label='ndB') # 2 curves
# Apply operation on the NdOverlays
dnda = op(nda, cmap='blue')
dndb = op(ndb, cmap='red')
# Create overlay of previous operation ouputs
ov = dnda * dndb
# Render
hv.render(ov) with these changes: diff --git a/holoviews/plotting/plot.py b/holoviews/plotting/plot.py
index 0a2ebbe07..8ebc8a1ce 100644
--- a/holoviews/plotting/plot.py
+++ b/holoviews/plotting/plot.py
@@ -1178,6 +1178,10 @@ class GenericElementPlot(DimensionedPlot):
self.stream_sources = stream_sources
else:
self.stream_sources = compute_overlayable_zorders(self.hmap)
+ print('Sources of element\n', element, end='\n')
+ from pprint import pprint
+ s = dict(self.stream_sources)
+ pprint({k: [f'{type(v).__name__}[{v.label!r}]' for v in s[k]] for k in s})
plot_element = self.hmap.last
if self.batched and not isinstance(self, GenericOverlayPlot):
@@ -1652,6 +1656,7 @@ class GenericOverlayPlot(GenericElementPlot):
# Get zorder and style counter
length = self.style_grouping
group_key = style_key[:length]
+ print('self.zorder:', self.zorder, 'oidx:', oidx, 'offset:', self.zoffset)
zorder = self.zorder + oidx + self.zoffset
cyclic_index = self.group_counter[group_key]
self.cyclic_index_lookup[style_key] = cyclic_index
@@ -1688,6 +1693,7 @@ class GenericOverlayPlot(GenericElementPlot):
stream_sources=self.stream_sources,
projection=self.projection, fontscale=self.fontscale,
zorder=zorder, root=self.root, **passed_handles)
+ print('plottype', plottype, 'zorder', zorder)
return plottype(obj, **plotopts)
prints:
The # output of `compute_overlayable_zorders(obj)`
{0: ["DynamicMap['c1']", "Curve['c1']", "NdOverlay['ndA']"],
1: ["Curve['c2']", "NdOverlay['ndA']"],
2: ["Curve['c3']", "NdOverlay['ndA']"],
3: ["DynamicMap['c4']", "Curve['c4']", "NdOverlay['ndB']"],
4: ["Curve['c5']", "NdOverlay['ndB']"]} The Some really dirty hack like injecting that before if zorder == 1:
zorder = 3 Now we need to understand a little better what's wrong and find a general solution. |
Good luck, that's probably up there with the hairiest code in HoloViews as it combines stream mapping and dynamic zorder remapping which are both individually some of the hairiest pieces of code. |
Here is another example that might help us triangulate the problem better: import holoviews as hv
from holoviews.operation.datashader import rasterize
hv.extension('bokeh')
curve_count = 1 # 1 works, 2 doesn't. With 'workaround' 2 works and 1 doesn't
ndoverlay = hv.NdOverlay({str(i):hv.Curve([1,2*i, 3*i]) for i in range(1,1+curve_count)})
rasterized = rasterize(ndoverlay).opts(width=800, height=400)
def inner(bounds):
if bounds is None:
return hv.Rectangles((1, 1, 2, 2))
else:
return hv.Rectangles((bounds[0], 1, 2, 2))
dmap = hv.DynamicMap(inner,streams=[hv.streams.BoundsXY()])
rasterized.opts(tools=['box_select']) * dmap Here
I think we need to collect these examples, figure out what the |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
ALL software version info
pip freeze
output:conda list
:Description of expected behavior and the observed behavior
Complete, minimal, self-contained example code that reproduces the issue
Stack traceback and/or browser JavaScript console output
Screenshots or screencasts of the bug in action
The text was updated successfully, but these errors were encountered: