-
Notifications
You must be signed in to change notification settings - Fork 10
Conversation
paramnb/__init__.py
Outdated
renderer = hv.Store.renderers[backend] | ||
plot = renderer.get_plot(value) | ||
plot.initialize_plot() | ||
size = (plot.state.plot_width, plot.state.plot_height) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use renderer.get_size
(needs changes in holoviews).
Cool! This functionality might be appropriate to move to a submodule, so that it's accessed as something like Is Output the right terminology here? @jlstevens and I have recently discussed adding output type specification to param, to allow a programmer to declare the result type of an operation like |
Sure.
Up to you, I make the distinction here between input and output widgets. Regular params are treated as input widgets and therefore respond to UI events changing the trait, while "output" params respond when you set the parameter value on the backend, by pushing that change to the frontend. |
Maybe it is more about viewing data? |
Once holoviz/holoviews#1140 is merged I can tidy this PR up. |
f4e9413
to
08b905a
Compare
Sounds reasonable, |
You mean |
Just one other suggestion: Not that great either to be honest...but |
Ended up going with |
paramnb/view.py
Outdated
""" | ||
Output parameters allow representing some output to be displayed. | ||
Output parameters may have a callback, which is called when a new | ||
value is set on the parameter. Additionally they should implement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docstring may need updating to match new "view" module naming.
paramnb/view.py
Outdated
|
||
class HView(_View): | ||
""" | ||
HView is an View parameter meant for displaying HoloViews objects. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"is a View"
paramnb/view.py
Outdated
HView is an View parameter meant for displaying HoloViews objects. | ||
In combination with HoloViews streams this parameter may be used | ||
to build complex dashboards. | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the docstring somehow mark this functionality as optional, making it clear paramnb does not depend on hv? I'm not sure if this functionality belongs here or in hv, but it seems like it's cleaner here? It's tricky to have things like this that link the two unrelated projects together so closely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, the only reason why I've included it is because it handles stuff which would be a pain otherwise, specifically correctly setting the size of the container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I wonder if that could be generalized, such that paramnb supports things that can return the size of the container, and holoviews provides an object with such capability, and these two just happen to match? That way paramnb doesn't know about hv, and hv doesn't know about paramnb, but they still work well together, and other non-hv packages could also work well with paramnb in the same way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is just to be extremely explicit about what we assume about this external object, and for hv to be extremely explicit about what that object provides, so that the point of intersection between the two projects is as small as possible and very clearly demarcated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could also express it differently and have a generic View Parameter, which lets you supply a custom rendering function and returns the HTML or a tuple of the HTML and the size.
Then we'd just need to put this function somewhere:
def render(value):
import holoviews as hv
backend = hv.Store.current_backend
renderer = hv.Store.renderers[backend]
plot = renderer.get_plot(value)
plot.initialize_plot()
size = renderer.get_size(plot)
return renderer.html(plot), size
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or better yet we could define something like this on the holoviews Renderer class:
def html_with_size(self, obj, fmt=None, css=None, comm=True, **kwargs):
plot = self.get_plot(obj)
self.initialize_plot()
size = self.get_size(plot)
html = self.html(plot, fmt, css, comm, **kwargs)
return html, size
Then you could do:
paramnb.view.View(default=hv.Curve(...), renderer=hv.Store.renderers['bokeh'].html_with_size)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds perfect, thanks!
The changes look good to me, though I did have trouble following some of the logic and thus I wasn't able to fully convince myself that I know precisely how it's working. |
Here's a rough summary: The View parameters have a callback slot, which paramnb hooks onto. When a View parameter is set, the callback is triggered, the render method converts the parameter state to HTML and finally the traitlet and therefore the display is updated. |
Sounds good in principle. |
@jbednar There's now only two View parameters, one for HTML output and one for Image (i.e. png output), and View parameters now accept a import holoviews as hv
import holoviews.plotting.mpl
renderer = hv.Store.renderers['matplotlib']
class Example(param.Parameterized):
amplitude = param.Number(default=2, bounds=(2, 5))
frequency = param.Number(default=2, bounds=(1, 10))
element = param.ObjectSelector(default=hv.Curve,
objects=[hv.Curve, hv.Scatter, hv.Area],
precedence=0)
output = paramnb.view.Image(renderer=lambda x: renderer(x)[0])
def update(self):
self.output = self.element(self.amplitude*np.sin(np.linspace(0, np.pi*self.frequency)))
example = Example()
paramnb.Widgets(example, callback=example.update, view_position='right') |
Sometimes I feel like my only useful function in life is to poke a stick at you until what you come up with is sufficiently brilliant. Looks beautiful to me. Ready to merge? |
:-)
Yes! |
This PR adds the concept of
Output
parameters and widgets to paramnb. Unlike the other parameter typesOutput
widgets do not respond to changes on the frontend instead the corresponding parameters have callbacks which are triggered when they are updated. This means that the display can be updated by setting the parameter, allowing plots to be switched in response to parameter changes.Output parameters differ from other parameters in two main ways:
They have a
callback
attribute, which allows paramnb to install itself as a callback, whenever the parameter value changes the callback is called and the ipywidgets traitlet is updated along with it.They have a
render
method, which allows rendering the current parameter value to HTML. This allows having custom output parameters like HoloViewsOutput, which automatically renders any HoloViews object to HTML.Simple HTML example:
To do: