ioam / parambokeh Goto Github PK
View Code? Open in Web Editor NEWGenerate widgets from Parameterized objects in Jupyter or Bokeh server
Home Page: https://ioam.github.com/parambokeh
License: BSD 3-Clause "New" or "Revised" License
Generate widgets from Parameterized objects in Jupyter or Bokeh server
Home Page: https://ioam.github.com/parambokeh
License: BSD 3-Clause "New" or "Revised" License
When first visiting the ParamBokeh web site, it looks broken because none of the widgets show up:
However, if I revisit that page in another tab, it now works:
And if I go back to the original tab after many minutes (more than two, less than 45) the widgets show up there too. The first time that happened, I did shift reload, in which case this cycle started again, and the second time the widgets were there after shift reload right away, and then the third time there was a pause again.
????
I have a parambokeh widget implemntation of param.Date.
Is it possible to display the time (HH:MM:SS) of the datetime object in addition to the Month DD, YYYY?
Is there a way to change that format?
The widget takes user input from a popup calendar. Is there a way for widget input from the user to include the time?
Is this indicative of any general problem with compatibility with bokeh 0.12.9 or is it just an outdated import?
In [1]: import parambokeh
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-1-a6ae99d594b0> in <module>()
----> 1 import parambokeh
~/anaconda/envs/hv/lib/python3.6/site-packages/parambokeh/__init__.py in <module>()
14 from bokeh.models import CustomJS
15
---> 16 from .comms import JupyterCommJS, JS_CALLBACK, notebook_show
17 from .widgets import wtype, literal_params
18 from .util import named_objs, get_method_owner
~/anaconda/envs/hv/lib/python3.6/site-packages/parambokeh/comms.py in <module>()
6 from bokeh.embed import notebook_div
7 from bokeh.io import _CommsHandle
----> 8 from bokeh.util.notebook import publish_display_data, get_comms
9
10 try:
ImportError: cannot import name 'publish_display_data'
Significant API changes in bokeh should reduce from 0.12.10 onwards, so I think it makes sense to make the next release of parambokeh target 0.12.10 and drop support for previous bokeh versions.
Below are things that don't seem to work (please add to this list!). Note: these things have not necessarily been working in previous versions, but it seems worthwhile fixing them all in one go for bokeh 0.12.10.
param.Number(default=0)
Ongoing work to fix these is in #17.
Using holoviews 1.10, I get the following traceback in the web console (View_Parameters.ipynb
notebook) when trying to switch to Scatter
in the last example:
VM337:45 Python callback returned following output:
Traceback (most recent call last):
File "/Users/jstevens/Desktop/development/holoviews/holoviews/plotting/util.py", line 260, in get_plot_frame
return map_obj[key]
File "/Users/jstevens/Desktop/development/holoviews/holoviews/core/spaces.py", line 1128, in __getitem__
self._cache(tuple_key, val)
File "/Users/jstevens/Desktop/development/holoviews/holoviews/core/spaces.py", line 1175, in _cache
self[key] = val
File "/Users/jstevens/Desktop/development/holoviews/holoviews/core/ndmapping.py", line 523, in __setitem__
self._add_item(key, value, update=False)
File "/Users/jstevens/Desktop/development/holoviews/holoviews/core/ndmapping.py", line 160, in _add_item
self._item_check(dim_vals, data)
File "/Users/jstevens/Desktop/development/holoviews/holoviews/core/ndmapping.py", line 824, in _item_check
(self.__class__.__name__, type(data).__name__, self.type.__name__))
AssertionError: DynamicMap must only contain one type of object, not both Scatter and Curve.
Actually, none of the widgets update that example right now, even just changing frequency and amplitude doesn't work. Eg. changing frequency gives this traceback in the web console:
Python failed with the following traceback: /Users/jstevens/miniconda3/envs/analytics/lib/python3.6/site-packages/traitlets/traitlets.py validate L2054
TraitError: The 'target_name' trait of a Comm instance must be a unicode string, but a value of CurvePlot(apply_extents=True, apply_ranges=True, bgcolor=None, border=10, default_tools=['save', 'pan', 'wheel_zoom', 'box_zoom', 'reset'], finalize_hooks=[], fontsize={'title': '12pt'}, gridstyle={}, height=300, interpolation='linear', invert_axes=False, invert_xaxis=False, invert_yaxis=False, labelled=['x', 'y'], lod={'factor': 10, 'interval': 300, 'threshold': 2000, 'timeout': 500}, logx=False, logy=False, name='CurvePlot01083', normalize=True, projection=None, shared_axes=True, shared_datasource=True, show_frame=True, show_grid=False, show_legend=True, show_title=True, sizing_mode='fixed', title_format='{label} {group} {dimensions}', toolbar='right', tools=[], width=300, xaxis='bottom', xrotation=None, xticks=None, yaxis='left', yrotation=None, yticks=None) <class 'holoviews.plotting.bokeh.chart.CurvePlot'> was specified.
Also, maybe some animated gifs on the homepage.
Right now, we check the notebooks run. However, that checks little about whether or not parambokeh works.
We could add some unit tests with pytest.
We could add some more advanced notebook tests.
We could at least check that bokeh models are created as expected.
I'm doing the tutorial at pyviz on the notebook 12_Parameters_and_Widgets and noticed the following, based on this experiment:
import holoviews as hv
import param
import paramnb
import parambokeh
class NumOptions(hv.streams.Stream):
intdef = param.Number(default=1, bounds=(0,10))
fourdig = param.Number(default=1.1234, bounds=(0,10))
bokopts = NumOptions(name='parambokeh')
nbopts = NumOptions(name='paramnb')
parambokeh.Widgets(bokopts), paramnb.Widgets(nbopts)
What happens here is that for parambokeh
, the precision of the slider is dependent on the number of significant digits of the initial value. So the slider for intdef
has integer values, and the slider for fourdig
has values to 4 places after the decimal point.
In the case of paramnb
, the precision is 2 digits, independent of the initial value.
I'm not sure what the actual behavior should be, but the inconsistent behavior can be confusing.
Maybe, for both cases, there should be a way to specify the precision of the slider as it is moved.
I.e. instead of displaying an uneditable value, the value should be editable.
I get this error when trying to use parambokeh in a Jupyter notebook. Example:
import numpy as np
import pandas as pd
from bokeh.models import HoverTool
import holoviews as hv
hv.extension("bokeh")
renderer = hv.renderer("bokeh")
# Remove Bokeh logo from plots (https://stackoverflow.com/questions/47585887/remove-bokeh-logo-in-holoviews)
def disable_logo(plot, element):
plot.state.toolbar.logo = None
hv.plotting.bokeh.ElementPlot.finalize_hooks.append(disable_logo)
import param, parambokeh
df = pd.DataFrame({"pax": ["a", "b", "c"], "val": [3, 1, 2], "day": ["Wednesday", "Thursday", "Friday"]})
class Test(hv.streams.Stream):
pax = param.ObjectSelector(default="ALL", objects=["ALL"] + np.unique(df["pax"]).tolist())
def make_view(self, **kwargs):
if self.pax != "ALL":
df_tmp = df[df["pax"] == self.pax]
else:
df_tmp = df
return hv.Bars(df_tmp, kdims=["day"], vdims=["val"])
explorer = Test(name="Test")
parambokeh.Widgets(explorer, callback=explorer.event)
hv.DynamicMap(explorer.make_view, streams=[explorer])
Error message:
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-60-df1791955b28> in <module>()
25
26 explorer = Test(name="Test")
---> 27 parambokeh.Widgets(explorer, callback=explorer.event)
28 hv.DynamicMap(explorer.make_view, streams=[explorer])
~\AppData\Local\Continuum\anaconda3\lib\site-packages\param\parameterized.py in __new__(class_, *args, **params)
1886 inst = class_.instance()
1887 inst._set_name(class_.__name__)
-> 1888 return inst.__call__(*args,**params)
1889
1890 def __call__(self,*args,**kw):
~\AppData\Local\Continuum\anaconda3\lib\site-packages\parambokeh\__init__.py in __call__(self, parameterized, doc, plots, **params)
108 if self.p.mode == 'notebook':
109 if not IPYTHON_AVAILABLE:
--> 110 raise ImportError('IPython is not available, cannot use '
111 'Widgets in notebook mode.')
112 self.comm = JupyterCommJS(on_msg=self.on_msg)
ImportError: IPython is not available, cannot use Widgets in notebook mode.
Was just looking at bokeh and noticed that the next release will likely get a dedicated NumberInput
widget (see bokeh/bokeh#7157) which will probably be superior to current solutions.
(or alternative way of displaying param docstring)
Param and ParamBokeh were designed to support large, complex systems, with hierarchically organized options mirroring a class hierarchy that allows a clean separation between parameters for objects and any widgets that might be appropriate to display when those objects are used in a GUI context. Thus parameters are all currently declared as class attributes of Parameter type, independently of any package like ParamBokeh that will create GUI widgets from those definitions. For complex systems, separating the parameter declaration from the widget instantiation provides major benefits to the code even apart from any widgets, such as type and range checking that helps keep interactions between components manageable.
However, there are other contexts where it would be useful to have Bokeh-based widgets that don't involve complex hierarchical systems, and the class Parameter approach is not necessarily the best approach in those cases. For instance, when using a Jupyter notebook as a command prompt, it's often useful to create a widget explicitly for a particular local task, without designing a class hierarchy. The API from ipywidgets' interact()
function is a good example of this alternative approach, which won't necessarily scale to larger projects, but can be very convenient in a single Jupyter cell or in a very basic dashboard.
Mirroring or nearly mirroring the interact()
API specifically would also make it easier for people to switch between ipywidgets and param-based approaches, e.g. to evaluate Bokeh Server as a deployment mechanism. If we provide an interact()
equivalent, we would need to be very clear in the documentation about its purpose, and to make its limitations clear.
From user guide example:
https://ioam.github.io/parambokeh/user_guide/View_Parameters.html
holoviews=1.10.5
parambokeh=0.2.2
/mnt/c/Users/sephi/GOOGLE~1/Bash/parambokeh/parambokeh/view.py in render_function(obj, view)
16 plot = renderer.get_plot(obj, doc=view._document)
17 if view._notebook:
---> 18 from holoviews.plotting.comms import JupyterComm
19 comm = JupyterComm(plot, view._comm_target)
20 plot.comm = comm
ModuleNotFoundError: No module named 'holoviews.plotting.comms'
I tried replacing that line with from pyviz_comms import JupyterComm
but then I get a new error stemming from on_init=True
input
32 example = CurveExample(name='HoloViews Example')
33 parambokeh.Widgets(example, callback=example.event, push=False,
---> 34 on_init=True, view_position='right')
~/anaconda3/lib/python3.6/site-packages/param/parameterized.py in __new__(class_, *args, **params)
1889 inst = class_.instance()
1890 inst._set_name(class_.__name__)
-> 1891 return inst.__call__(*args,**params)
1892
1893 def __call__(self,*args,**kw):
/mnt/c/Users/sephi/GOOGLE~1/Bash/parambokeh/parambokeh/__init__.py in __call__(self, parameterized, doc, plots, **params)
187
188 if self.p.on_init:
--> 189 self.execute()
190
191 if self.p.mode == 'raw':
/mnt/c/Users/sephi/GOOGLE~1/Bash/parambokeh/parambokeh/__init__.py in execute(self, changed)
381 if self.p.callback is not None:
382 if get_method_owner(self.p.callback) is self.parameterized:
--> 383 self.p.callback(**changed)
384 else:
385 self.p.callback(self.parameterized, **changed)
<ipython-input-8-65291cacb15b> in event(self, **kwargs)
26 def event(self, **kwargs):
27 if not self.output or any(k in kwargs for k in ['color', 'element']):
---> 28 self.output = hv.DynamicMap(self.view, streams=[self])
29 else:
30 super(CurveExample, self).event(**kwargs)
/mnt/c/Users/sephi/GOOGLE~1/Bash/parambokeh/parambokeh/view.py in __set__(self, obj, val)
48 obj_id = id(obj)
49 if obj_id in self.callbacks:
---> 50 self.callbacks[obj_id](self.renderer(val, self))
51
52
/mnt/c/Users/sephi/GOOGLE~1/Bash/parambokeh/parambokeh/view.py in render_function(obj, view)
17 if view._notebook:
18 from pyviz_comms import JupyterComm
---> 19 comm = JupyterComm(plot, view._comm_target)
20 plot.comm = comm
21 plot.document = view._document
~/anaconda3/lib/python3.6/site-packages/pyviz_comms/__init__.py in __init__(self, id, on_msg)
193 self._on_msg = on_msg
194 self._comm = None
--> 195 super(Comm, self).__init__(id = id if id else uuid.uuid4().hex)
196
197
~/anaconda3/lib/python3.6/site-packages/param/parameterized.py in __init__(self, **params)
1039 self.__generate_name()
1040
-> 1041 self._setup_params(**params)
1042 object_count += 1
1043
~/anaconda3/lib/python3.6/site-packages/param/parameterized.py in override_initialization(parameterized_instance, *args, **kw)
976 original_initialized=parameterized_instance.initialized
977 parameterized_instance.initialized=False
--> 978 fn(parameterized_instance,*args,**kw)
979 parameterized_instance.initialized=original_initialized
980 return override_initialization
~/anaconda3/lib/python3.6/site-packages/param/parameterized.py in _setup_params(self, **params)
1439 self.warning("Setting non-parameter attribute %s=%s using a mechanism intended only for parameters",name,val)
1440 # i.e. if not desc it's setting an attribute in __dict__, not a Parameter
-> 1441 setattr(self,name,val)
1442
1443
~/anaconda3/lib/python3.6/site-packages/param/parameterized.py in __set__(self, obj, val)
535
536 def __set__(self,obj,val):
--> 537 self._check_value(val)
538 super(String,self).__set__(obj,val)
539
~/anaconda3/lib/python3.6/site-packages/param/parameterized.py in _check_value(self, val)
532 def _check_value(self,val):
533 if not isinstance(val, self.basestring) and not (self.allow_None and val is None):
--> 534 raise ValueError("String '%s' only takes a string value."%self._attrib_name)
535
536 def __set__(self,obj,val):```
How to run the Sample django + parambokeh apps on a web server other than on a local machine?
The web server is an Apache http server running on an EC2 single instance, listening on port 80.
I tried many different host addresses and ports configurations but I don't really understand how things work.
I believe that the following bk_worker code starts the the bokeh server in the background when a new thread is started:
def bk_worker():
server = Server({'/bk_sliders_app': bk_sliders.app},
io_loop=IOLoop(),
address=bk_config.server['address'],
port=bk_config.server['port'],
allow_websocket_origin=["localhost:8000"])
server.start()
server.io_loop.start()
What should be the address and port specified there? It is currently set to localhost and 5006 because I believe that, since Server() is called on the web server, then it should spawn a bokeh server on the same local host, correct? If not, then what should be the address and port (I also tried 0.0.0.0 but it didn't work)?
I believe that the bokeh server has started because I see a thread running under the wsgi user and started by httpd when running ps -ael on the EC2 instance:
4 S 0 20701 3057 0 80 0 - 62977 - ? 00:00:00 httpd
0 S 0 20705 20701 0 80 0 - 6295 - ? 00:00:00 rotatelogs
5 S 497 20706 20701 0 80 0 - 247053 - ? 00:00:01 httpd
Is there a better way to check that the bokeh server is running correctly and is there a way to see a log from the bokeh server?
I slightly modified the base.html template to display the output of server_document() called from view.py:
<title>parambokeh in django: sliders</title>The script returned when accessing the http://django2-env.xpy8pjmgjb.us-east-2.elasticbeanstalk.com/sliders/ url is
<script src="http://localhost:5006/bk_sliders_app/autoload.js?bokeh-autoload-element=1002&bokeh-app-path=/bk_sliders_app&bokeh-absolute-url=http://localhost:5006/bk_sliders_app" id="1002"></script>Where does this script run? Does it run on the client browser or does it run on the web server? If it runs on the client, then the http://localhost:5006 src should be incorrect and should be django2-env.xpy8pjmgjb.us-east-2.elasticbeanstalk.com instead, correct? Then what about the port number? 5006 is not open to internet access, so should it be port 80 instead? In this case, do I need to setup the Apache http server as a proxy/reverse proxy? If yes, how do I do it?
Setting Range bounds=None
(or not providing them) results in a misleading error:
float_range = param.Range(default=(0.0, 1.57), bounds=None)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-8-ede5c729d901> in <module>()
6 colormap = param.ObjectSelector(default='rainbow', objects=['rainbow', 'bgy', 'bgyw', 'blues', 'coolwarm', 'gray,'])
7 opts = plot_options(name='')
----> 8 parambokeh.Widgets(opts)
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\param\parameterized.py in __new__(class_, *args, **params)
2047 inst = class_.instance()
2048 inst.param._set_name(class_.__name__)
-> 2049 return inst.__call__(*args,**params)
2050
2051 def __call__(self,*args,**kw):
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\parambokeh\__init__.py in __call__(self, parameterized, doc, plots, **params)
232
233 # Initialize widgets and populate container
--> 234 widgets, views = self.widgets()
235 plots = views + plots
236 widget_box.children = widgets
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\parambokeh\__init__.py in widgets(self)
495
496 if self.p.show_labels:
--> 497 widgets += [self.widget(pname) for pname in ordered_params]
498 else:
499 widgets += [self.widget(pname) for pname in ordered_params]
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\parambokeh\__init__.py in <listcomp>(.0)
495
496 if self.p.show_labels:
--> 497 widgets += [self.widget(pname) for pname in ordered_params]
498 else:
499 widgets += [self.widget(pname) for pname in ordered_params]
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\parambokeh\__init__.py in widget(self, param_name)
459 """Get widget for param_name"""
460 if param_name not in self._widgets:
--> 461 self._widgets[param_name] = self._make_widget(param_name)
462 return self._widgets[param_name]
463
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\parambokeh\__init__.py in _make_widget(self, p_name)
403 kw['start'], kw['end'] = p_obj.get_soft_bounds()
404
--> 405 w = widget_class(**kw)
406
407 if hasattr(p_obj, 'callbacks') and value is not None:
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\parambokeh\widgets.py in RangeWidget(*args, **kw)
92 if isinstance(kw['start'], int) and isinstance(kw['end'], int):
93 kw['step'] = 1
---> 94 return RangeSlider(*args, **kw)
95
96 def PlotWidget(*args, **kw):
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\bokeh\models\widgets\sliders.py in __init__(self, **kwargs)
22 if 'start' in kwargs and 'end' in kwargs:
23 if kwargs['start'] == kwargs['end']:
---> 24 raise ValueError("Slider 'start' and 'end' cannot be equal.")
25 super(Widget, self).__init__(**kwargs)
26
ValueError: Slider 'start' and 'end' cannot be equal.
Can you put up a minimal working example (e.g., in a doc notebook) of how to use parambokeh with the bokeh server? I've been trying it out in the notebook but I can't get it to work with a server.
One feature parambokeh currently lacks before it has full feature parity with paramnb is Recursive editing.
Mainly with and without notebook installed.
here: https://github.com/ioam/parambokeh/blob/master/parambokeh/__init__.py#L16
Looks like this is the exception being raised; doesn't seem to be the one intended to be caught. Seems to have popped up with bokeh 0.12.10.
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-14-119ad22f1a00> in <module>()
----> 1 from parambokeh.comms import JupyterCommJS, JS_CALLBACK, notebook_show
~/.local/lib/python3.6/site-packages/parambokeh-0.2.1-py3.6.egg/parambokeh/comms.py in <module>()
4 import traceback
5
----> 6 from bokeh.embed import notebook_div
7
8 from IPython.display import publish_display_data
ImportError: cannot import name 'notebook_div'
name = param.String(default='a name')
Here it's overlapping with CurveExample(name='HoloViews Example')
import param
import parambokeh
from bokeh.io import output_notebook
import numpy as np
import pandas as pd
output_notebook()
import holoviews as hv
class CurveExample(hv.streams.Stream):
color = param.Color(default='#000000', precedence=0)
element = param.ObjectSelector(default=hv.Curve,
objects=[hv.Curve, hv.Scatter, hv.Area],
precedence=0)
amplitude = param.Number(default=2, bounds=(2, 5))
frequency = param.Number(default=2, bounds=(1, 10))
name = param.String(default='Hello')
output = parambokeh.view.Plot()
def view(self, *args, **kwargs):
return self.element(self.amplitude*np.sin(np.linspace(0, np.pi*self.frequency)),
vdims=[hv.Dimension('y', range=(-5, 5))]).opts(style=dict(color=self.color)) * hv.Text(20, 3, self.name)
def event(self, **kwargs):
if not self.output or any(k in kwargs for k in ['color', 'element']):
self.output = hv.DynamicMap(self.view, streams=[self], cache_size=0)
else:
super(CurveExample, self).event(**kwargs)
example = CurveExample(name='HoloViews Example')
parambokeh.Widgets(example, callback=example.event, on_init=True, view_position='right')
I have a param.Parameterized
class with a bunch of Booleans. If the parambokeh.Widge
t has it toggled as True
, I want to collect that value and process it. My problem is that what I get back from param is a param.Boolean object
. In many other cases, python just understands it, but when I check that value against True
its not understood. My current workaround is to use val.__get__(None,None)
but surely there is a better approach?
Test snippet:
import param
class BaseClass(param.Parameterized):
boolean1 = param.Boolean(True, doc="A sample Boolean parameter")
boolean2 = param.Boolean(False, doc="A sample Boolean parameter")
def widget_to_list(self):
for name, val in self.params().items():
if val.__get__(None,None) is True:
print(val.__get__(None,None))
base = BaseClass()
base.widget_to_list()
pip install parambokeh or pip install parambokeh[examples] to be able to run the examples
conda install -c pyviz parambokeh
or conda install -c pyviz parambokeh holoviews bokeh ... etc
to be able to run the examples
Is there a way to get labels on the side of widget as opposed to on top of the widget?
I'm having trouble making a holoviews/parambokeh widgety-thing work with a datashader plot as output:
import param
import parambokeh
from holoviews.operation.datashader import datashade, dynspread
import colorcet as cc
class WidgetTest(hv.streams.Stream):
cmap = param.ObjectSelector(default='coolwarm',
objects=['coolwarm', 'fire', 'blue'])
output = parambokeh.view.Plot()
def __init__(self, pts, *args, **kwargs):
super(WidgetTest, self).__init__(*args, **kwargs)
self.pts = pts
def event(self, **kwargs):
super(WidgetTest, self).event
self.output = datashade(self.pts, cmap=cc.palette[self.cmap])
When I run the following, the plot doesn't update on changing the colormap with the widget. What am I missing?
import numpy as np
n = 100000
pts = hv.Points(np.random.multivariate_normal([0,0], [[1,0], [0,1]], size=n))
example = WidgetTest(pts)
parambokeh.Widgets(example, callback=example.event, push=False,
on_init=True, view_position='right')
Ideally they should have step that depends on the precision of the associated input value (#18).
Wasn't sure whether this is an upstream (bokeh) issue or a param issue, so I decided to try and put it here first in parambokeh. I noticed there is a possibility of setting DateRange parameters in param since holoviz/param#168, so I thought about making a DateRange slider using param.DateRange, similar to the param.Range parameter. Inspiration taken from this jupyter notebook.
I create a class like so:
!pip install --upgrade https://github.com/ioam/param/archive/master.zip #requires https://github.com/ioam/param/pull/168
class IceSatExplorer(hv.streams.Stream):
colormap = param.ObjectSelector(default=cm["isolum"], objects=cm.values())
altitude = param.Range(default=(minAlt, maxAlt), bounds=(minAlt, maxAlt))
timerange = param.DateRange(default=(minTime, maxTime), bounds=(minTime, maxTime))
def make_view(self, x_range=None, y_range=None, **kwargs):
...
And call it using:
explorer = IceSatExplorer()
parambokeh.Widgets(explorer, callback=explorer.event)
hv.DynamicMap(explorer.make_view, streams=[explorer, RangeXY()])
which results in an error complaining:
ValueError: expected an element of Tuple(Float, Float), got (Timestamp('2003-02-20 11:16:02.592235'), Timestamp('2003-02-23 03:41:56.198538'))
I've put together a Jupyter notebook (.ipynb) at this gist, but with the timerange = param.DateRange(...)
line commented out so it works as so:
Below is the full error reported if I uncomment the timerange = param.DateRange(...)
. Final error points to this code block:
ValueError Traceback (most recent call last)
<ipython-input-8-77a7ec6347eb> in <module>()
1 explorer = IceSatExplorer()
2 #paramnb.Widgets(explorer, callback=explorer.event)
----> 3 parambokeh.Widgets(explorer, callback=explorer.event)
4 hv.DynamicMap(explorer.make_view, streams=[explorer, RangeXY()])
~/miniconda3/lib/python3.6/site-packages/param/parameterized.py in __new__(class_, *args, **params)
1889 inst = class_.instance()
1890 inst._set_name(class_.__name__)
-> 1891 return inst.__call__(*args,**params)
1892
1893 def __call__(self,*args,**kw):
~/miniconda3/lib/python3.6/site-packages/parambokeh/__init__.py in __call__(self, parameterized, doc, plots, **params)
121 self.shown = False
122
--> 123 widgets, views = self.widgets()
124 plots = views + plots
125 container = widgetbox(widgets, width=self.width)
~/miniconda3/lib/python3.6/site-packages/parambokeh/__init__.py in widgets(self)
346
347 if self.p.show_labels:
--> 348 widgets += [self.widget(pname) for pname in ordered_params]
349 else:
350 widgets += [self.widget(pname) for pname in ordered_params]
~/miniconda3/lib/python3.6/site-packages/parambokeh/__init__.py in <listcomp>(.0)
346
347 if self.p.show_labels:
--> 348 widgets += [self.widget(pname) for pname in ordered_params]
349 else:
350 widgets += [self.widget(pname) for pname in ordered_params]
~/miniconda3/lib/python3.6/site-packages/parambokeh/__init__.py in widget(self, param_name)
310 """Get widget for param_name"""
311 if param_name not in self._widgets:
--> 312 self._widgets[param_name] = self._make_widget(param_name)
313 return self._widgets[param_name]
314
~/miniconda3/lib/python3.6/site-packages/parambokeh/__init__.py in _make_widget(self, p_name)
261 kw['start'], kw['end'] = p_obj.get_soft_bounds()
262
--> 263 w = widget_class(**kw)
264
265 if hasattr(p_obj, 'callbacks') and value is not None:
~/miniconda3/lib/python3.6/site-packages/parambokeh/widgets.py in RangeWidget(*args, **kw)
53 if isinstance(kw['start'], int) and isinstance(kw['end'], int):
54 kw['step'] = 1
---> 55 return RangeSlider(*args, **kw)
56
57 def PlotWidget(*args, **kw):
~/miniconda3/lib/python3.6/site-packages/bokeh/model.py in __init__(self, **kwargs)
218 self._id = kwargs.pop("id", make_id())
219 self._document = None
--> 220 super(Model, self).__init__(**kwargs)
221 default_theme.apply_to_model(self)
222
~/miniconda3/lib/python3.6/site-packages/bokeh/core/has_props.py in __init__(self, **properties)
234
235 for name, value in properties.items():
--> 236 setattr(self, name, value)
237
238 def __setattr__(self, name, value):
~/miniconda3/lib/python3.6/site-packages/bokeh/core/has_props.py in __setattr__(self, name, value)
262
263 if name in props or name in deprecated:
--> 264 super(HasProps, self).__setattr__(name, value)
265 else:
266 matches, text = difflib.get_close_matches(name.lower(), props), "similar"
~/miniconda3/lib/python3.6/site-packages/bokeh/core/property/descriptors.py in __set__(self, obj, value, setter)
501 raise RuntimeError("%s.%s is a readonly property" % (obj.__class__.__name__, self.name))
502
--> 503 self._internal_set(obj, value, setter=setter)
504
505 def __delete__(self, obj):
~/miniconda3/lib/python3.6/site-packages/bokeh/core/property/descriptors.py in _internal_set(self, obj, value, hint, setter)
722
723 '''
--> 724 value = self.property.prepare_value(obj, self.name, value)
725
726 old = self.__get__(obj, obj.__class__)
~/miniconda3/lib/python3.6/site-packages/bokeh/core/property/bases.py in prepare_value(self, obj_or_cls, name, value)
279 break
280 else:
--> 281 raise e
282 else:
283 value = self.transform(value)
~/miniconda3/lib/python3.6/site-packages/bokeh/core/property/bases.py in prepare_value(self, obj_or_cls, name, value)
272 def prepare_value(self, obj_or_cls, name, value):
273 try:
--> 274 self.validate(value)
275 except ValueError as e:
276 for tp, converter in self.alternatives:
~/miniconda3/lib/python3.6/site-packages/bokeh/core/properties.py in validate(self, value)
1386 if not (isinstance(value, (tuple, list)) and len(self.type_params) == len(value) and \
1387 all(type_param.is_valid(item) for type_param, item in zip(self.type_params, value))):
-> 1388 raise ValueError("expected an element of %s, got %r" % (self, value))
1389
1390 def _sphinx_type(self):
ValueError: expected an element of Tuple(Float, Float), got (Timestamp('2003-02-20 11:16:02.592235'), Timestamp('2003-02-23 03:41:56.198538'))
This issue summarizes a discussion I had with @jbednar, @philippjfr and @ceball about building dashboard with parambokeh and bokeh server.
We believe we can build dashboards in a fairly flexible and general way using a three level hierarchy:
For step 2, you can either use mode='raw'
and build a bokeh layout for yourself or you can supply a bokeh model in plots
and a view_position
. There are a few ways this could be improved:
I'm not sure how this will work when multiple bokeh models are supplied to plots
and to be honest, I haven't checked how it works right now , maybe the widgets are placed in view_position
relative to the first element in plots
?
One other thing we discussed was the possibility of associating a visualization with corresponding parameters/widgets at the param level and not at the parambokeh level. The idea is that parambokeh would be able to generate a default visualization (with widgets) given a parameterized object and nothing else. You would then be able to customize the details of this visualization by supplying optional information to paramb.
We also discussed how holoviews widgets could fit into this system: perhaps the holoviews widgets would use bokeh widgets and for matplotlib support, we could simply output Div
models in a bokeh layout where the Div
holds the matplotlib output.
import param, parambokeh
class Example(param.Parameterized):
single_file = param.FileSelector(path='*.xyz',precedence=0.5)
parambokeh.Widgets(Example)
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-37-8b2a7dc851db> in <module>()
----> 1 parambokeh.Widgets(Example)
~/x/y/param/parameterized.py in __new__(class_, *args, **params)
1886 inst = class_.instance()
1887 inst._set_name(class_.__name__)
-> 1888 return inst.__call__(*args,**params)
1889
1890 def __call__(self,*args,**kw):
~/x/y/parambokeh3/parambokeh/__init__.py in __call__(self, parameterized, doc, plots, **params)
133 self.shown = False
134
--> 135 widgets, views = self.widgets()
136 plots = views + plots
137 container = widgetbox(widgets, width=self.p.width)
~/x/y/parambokeh3/parambokeh/__init__.py in widgets(self)
372
373 if self.p.show_labels:
--> 374 widgets += [self.widget(pname) for pname in ordered_params]
375 else:
376 widgets += [self.widget(pname) for pname in ordered_params]
~/x/y/parambokeh3/parambokeh/__init__.py in <listcomp>(.0)
372
373 if self.p.show_labels:
--> 374 widgets += [self.widget(pname) for pname in ordered_params]
375 else:
376 widgets += [self.widget(pname) for pname in ordered_params]
~/x/y/parambokeh3/parambokeh/__init__.py in widget(self, param_name)
336 """Get widget for param_name"""
337 if param_name not in self._widgets:
--> 338 self._widgets[param_name] = self._make_widget(param_name)
339 return self._widgets[param_name]
340
~/x/y/parambokeh3/parambokeh/__init__.py in _make_widget(self, p_name)
272 kw['value'] = [lookup[v] for v in value]
273 else:
--> 274 kw['value'] = lookup[value]
275 opt_lookup = {k: v for k, v in options}
276 self._widget_options[p_name] = opt_lookup
We were hoping to eliminate the mode
argument entirely but currently I don't see how, failing that we should have a better error message when the IPython import fails (or better automatically fall back to server mode in that case).
See #7
I was trying to do this with DynamicMap, but kept getting errors when I tried instantiating a DynamicMap inside a DynamicMap callback. I have some data that looks (roughly) like:
{ project1: { step1: [1,2,3], step2: [10,11,12]},
project2: {step2: [15,16,17], step3: [20,21,22]} }
Basically, the first pull-down should have Select between project1 and project2. If I select project1, then my step pull-down should be step1, step2. If I select project2, the step pull-down should be step2, step3.
Will parambokeh do this? I'm also not quite sure how to fit this into holoviews.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.