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

Add ParamRef baseclass for ParamFunction and ParamMethod #6392

Merged
merged 8 commits into from
Feb 26, 2024

Conversation

philippjfr
Copy link
Member

@philippjfr philippjfr commented Feb 26, 2024

The class hierarchy for ParamFunction and ParamMethod has been quite confusing since their inception. Specifically ParamMethod was a subclass of ParamFunction, which conceptually makes no sense. Additionally, since we added generalized support and the concept of non-function references, there was no component in Panel that could take a generic reference and resolve it. Therefore we introduce the new ParamRef component in the class hierarchy, which forms a base class for both ParamMethod and ParamFunction. Not only is this organization now conceptually correct, but it also patches a hole in the Panel API which is to provide a component that can simply render the current value of a reference such as a parameter, widget, or reactive expression. Unlike ParamFunction, ParamRef will not have any display priority, i.e. a parameter will still be rendered using the Param pane, i.e. as a widget, but if e.g. we want to display the output of a widget or reactive expression the ParamRef pane comes in helpful.

Let's see an example:

ticker = pn.widgets.Select(name='Ticker', options=tickers)
window = pn.widgets.IntSlider(name='Window Size', value=6, start=1, end=51, step=5)

plots = {
    'altair': pn.pane.Vega(pn.bind(get_altair, ticker, window)),
    'hvplot': pn.pane.HoloViews(pn.bind(get_hvplot, ticker, window)),
    'matplotlib': pn.pane.Matplotlib(pn.bind(get_mpl, ticker, window), format='svg', sizing_mode='stretch_width'),
    'plotly': pn.pane.Plotly(pn.bind(get_plotly, ticker, window))
}

backend = pn.widgets.Select(name='Backend', options=plots)

pn.Row(
    pn.Column(backend, ticker, window),
    pn.param.ParamRef(backend)
).servable()
Screenshot 2024-02-26 at 15 06 23

Here the backend widget allows selecting between a few values while the ParamRef pane can be used to resolve and render the currently selected component.

Alternatives

Currently there are some alternatives to this new API but they are either not general enough or cumbersome to use.

1. Reference binding

One alternative is passing the reference to some other pane to resolve, e.g. this works well if the type of the object is well defined, e.g.:

pn.pane.DataFrame(df_parameter)

Here the DataFrame pane will resolve the value and correctly and efficiently update the output but in our example above there is no pane that can render Vega, HoloViews etc. types.

2. Layout reference binding

In the case where the return value is a list of components we can once again use reference binding to render multiple objects, e.g.:

multi_select = pn.widgets.MultiSelect(options=plots, value=[plots['altair'], plots['hvplot']])

pn.Row(multi_select, pn.FlexBox(objects=multi_select))
Screenshot 2024-02-26 at 15 27 42

3. Reactive Expression pane

Lastly we do have the option of rendering the component as a reactive expression using the existing ReactiveExpr pane. This works but requires a few workarounds for the simpler cases, e.g. to render the value of a select widget we have to call .rx() to turn our valid reference into a reactive expression and we also then have to disable rendering of the widgets:

pn.Row(
    pn.Column(backend, ticker, window),
    pn.param.ReactiveExpr(backend.rx(), show_widgets=False)
).servable()

Future work

As I finish writing #6289 and the remaining tutorials mentioned in #6390 I will also finally try to work out how to correctly document this important, but as of yet under-explained portion of the Panel API.

Copy link

codecov bot commented Feb 26, 2024

Codecov Report

Attention: Patch coverage is 85.48387% with 9 lines in your changes are missing coverage. Please review.

Project coverage is 83.63%. Comparing base (08b8632) to head (0d082b8).

Files Patch % Lines
panel/param.py 85.24% 9 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #6392       +/-   ##
===========================================
+ Coverage   39.59%   83.63%   +44.04%     
===========================================
  Files         305      305               
  Lines       45650    45682       +32     
===========================================
+ Hits        18075    38207    +20132     
+ Misses      27575     7475    -20100     
Flag Coverage Δ
ui-tests 39.60% <51.61%> (+<0.01%) ⬆️
unitexamples-tests 71.66% <85.48%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

panel/param.py Show resolved Hide resolved
panel/param.py Outdated Show resolved Hide resolved
panel/param.py Outdated Show resolved Hide resolved
panel/param.py Outdated Show resolved Hide resolved
Co-authored-by: Simon Høxbro Hansen <simon.hansen@me.com>
panel/param.py Show resolved Hide resolved
panel/param.py Outdated Show resolved Hide resolved
panel/param.py Show resolved Hide resolved
Copy link
Member Author

@philippjfr philippjfr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will merge, if anyone doesn't like the name please chime in soon so it can be renamed before an RC.

@philippjfr
Copy link
Member Author

There's likely some follow up work on ReactiveExpr but again that can happen later.

@philippjfr philippjfr merged commit 9e70185 into main Feb 26, 2024
15 checks passed
@philippjfr philippjfr deleted the param_modernize branch February 26, 2024 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants