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

Widgets ignore dimension streams #860

Merged
merged 5 commits into from Sep 12, 2016
Merged
Changes from 4 commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.
+46 −29
Diff settings

Always

Just for now

Copy path View file
@@ -803,15 +803,23 @@ def dimensionless_contents(streams, kdims):
with any of the key dimensions.
"""
names = stream_parameters(streams)
kdim_names = [kdim.name for kdim in kdims]
return [name for name in names if name not in kdim_names]
return [name for name in names if name not in kdims]


def streamless_dimensions(streams, kdims):
"""

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

I feel we need a better word for streamless_dimensions. These used to be simply 'key dimensions' before streams came along!

In other words, I would like a way to define these things in terms of what they are instead of what they are not. I can't say I have any great suggestions right now 'widget_dimensions', 'requested_dimensions', 'unbound_dimensions'? Got any ideas?

Return a list of dimensions that have not been associated with
any streams.
"""
params = stream_parameters(streams)
return [d for d in kdims if d not in params]


def wrap_tuple_streams(unwrapped, kdims, streams):
"""
Fills in tuple keys with dimensioned stream values as appropriate.
"""
param_groups = [(s.params().keys(), s) for s in streams]
param_groups = [(s.contents.keys(), s) for s in streams]
pairs = [(name,s) for (group, s) in param_groups for name in group]

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

Thanks! Made the same mistake twice!

substituted = []
for pos,el in enumerate(wrap_tuple(unwrapped)):
@@ -824,6 +832,16 @@ def wrap_tuple_streams(unwrapped, kdims, streams):
return tuple(substituted)


def drop_streams(streams, keys, kdims):
"""
Drop any dimensionsed streams from the keys and kdims.

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

Typo in 'dimensioned' and maybe add a line saying what it returns.

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

I still think it is a little odd to put the keys (typically a very long list) before the kdims (much shorter). The order that feels (slightly) more natural to me for the signature is (streams, kdims, keys). As there can be a long list of streams, the next best is probably (kdims, streams, keys).

Just a minor point that you may ignore if you wish!

"""
stream_params = stream_parameters(streams)
inds, dims = zip(*[(ind, kdim) for ind, kdim in enumerate(kdims)
if kdim not in stream_params])
return dims, [tuple(key[ind] for ind in inds) for key in keys]


def itervalues(obj):
"Get value iterator from dictionary for Python 2 and 3"
return iter(obj.values()) if sys.version_info.major == 3 else obj.itervalues()
@@ -43,10 +43,6 @@ def _plot_figure(self, idx, fig_format='json'):
msg = dict(patch=json_patch, root=self.plot.state._id)
msg = serialize_json(msg)
return msg
else:
self.plot.push()
return "Complete"


class BokehSelectionWidget(BokehWidget, SelectionWidget):
pass
@@ -32,15 +32,6 @@ def _plot_figure(self, idx):
return self.renderer.html(self.plot, figure_format, comm=False)


def update(self, key):
if self.plot.dynamic == 'bounded' and not isinstance(key, int):
key = tuple(dim.values[k] if dim.values else k
for dim, k in zip(self.mock_obj.kdims, tuple(key)))
self.plot[key]
self.plot.push()
return '' if self.renderer.mode == 'nbagg' else 'Complete'


def get_frames(self):
if self.renderer.mode == 'nbagg':
manager = self.plot.comm.get_figure_manager()
Copy path View file
@@ -484,10 +484,9 @@ def refresh(self, **kwargs):
the updated data if the plot has an associated Comm.
"""
traverse_setter(self, '_force', True)
if self.current_key:
self.update(self.current_key)
else:
self.update(0)
key = self.current_key if self.current_key else self.keys[0]
stream_key = util.wrap_tuple_streams(key, self.dimensions, self.streams)
self.update(stream_key)
if self.comm is not None:

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

It is a relief to see how simple this bit turned out to be.

self.push()

@@ -573,6 +572,7 @@ def __init__(self, element, keys=None, ranges=None, dimensions=None,
**dict(params, **plot_opts))
if top_level:
self.comm = self.init_comm(element)
self.streams = self.hmap.streams if isinstance(self.hmap, DynamicMap) else []

# Update plot and style options for batched plots
if self.batched:
@@ -920,6 +920,9 @@ def __init__(self, layout, keys=None, dimensions=None, **params):
**params)
if top_level:
self.comm = self.init_comm(layout)
self.streams = [s for streams in layout.traverse(lambda x: x.streams,
[DynamicMap])

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

The wrapping is a bit weird. I would put in layout.traverse(lambda x: x.streams, [DynamicMap]) onto the second line and for s in streams onto the third line.

for s in streams]


def _get_frame(self, key):
@@ -11,7 +11,7 @@
import param
from ..core.io import Exporter
from ..core.options import Store, StoreOptions, SkipRendering
from ..core.util import find_file, unicode
from ..core.util import find_file, unicode, streamless_dimensions
from .. import Layout, HoloMap, AdjointLayout
from .widgets import NdWidget, ScrubberWidget, SelectionWidget

@@ -201,9 +201,10 @@ def _validate(self, obj, fmt):
holomap_formats = self.mode_formats['holomap'][self.mode]

if fmt in ['auto', None]:
if ((len(plot) == 1 and not plot.dynamic)
if (((len(plot) == 1 and not plot.dynamic)
or (len(plot) > 1 and self.holomap is None) or
(plot.dynamic and len(plot.keys[0]) == 0)):
(plot.dynamic and len(plot.keys[0]) == 0)) or
not streamless_dimensions(plot.streams, plot.dimensions)):
fmt = fig_formats[0] if self.fig=='auto' else self.fig
else:
fmt = holomap_formats[0] if self.holomap=='auto' else self.holomap
@@ -8,7 +8,8 @@
from ...core import OrderedDict, NdMapping
from ...core.options import Store
from ...core.util import (dimension_sanitizer, safe_unicode,
unique_array, unicode, isnumeric)
unique_array, unicode, isnumeric,
wrap_tuple_streams, drop_streams)
from ...core.traversal import hierarchical

def escape_vals(vals, escape_numerics=True):
@@ -106,9 +107,8 @@ def __init__(self, plot, renderer=None, **params):
super(NdWidget, self).__init__(**params)
self.id = plot.comm.target if plot.comm else uuid.uuid4().hex
self.plot = plot
self.dimensions = plot.dimensions
self.keys = plot.keys

dims, keys = drop_streams(plot.streams, plot.keys, plot.dimensions)
self.dimensions, self.keys = dims, keys

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

As the variables dims and keys don't seem to be used in this method for anything other than setting self.dimensions and self.keys, I would consider using:

self.dimensions, self.keys = drop_streams(plot.streams, 
                                          plot.keys, 
                                          plot.dimensions)
self.json_data = {}
if self.plot.dynamic: self.embed = False
if renderer is None:
@@ -194,7 +194,9 @@ def _plot_figure(self, idx):


def update(self, key):
return self._plot_figure(key)
self.plot.update(key)
self.plot.push()
return 'Complete'

This comment has been minimized.

Copy link
@jlstevens

jlstevens Sep 12, 2016

Contributor

'Update Complete' maybe? Is 'Complete' by itself informative enough? I'm assuming this might be something that appears in the console. If it is a message/part of a protocol, it is probably not worth changing.

This comment has been minimized.

Copy link
@philippjfr

philippjfr Sep 12, 2016

Author Contributor

Currently part of the protocol, which will change as soon as we use comms for everything.




@@ -370,4 +372,10 @@ def update(self, key):
if self.plot.dynamic:
key = tuple(dim.values[k] if dim.values else k
for dim, k in zip(self.mock_obj.kdims, tuple(key)))
return self._plot_figure(key)
key = [key[self.dimensions.index(kdim)] if kdim in self.dimensions else None
for kdim in self.plot.dimensions]
key = wrap_tuple_streams(tuple(key), self.plot.dimensions,
self.plot.streams)
self.plot.update(key)
self.plot.push()
return 'Complete'
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.