Package: leda
ledaGenerate static HTML reports with interactive widgets from Jupyter notebooksInstallationledais available onPyPI:pipinstallledaQuick StartGenerationTo generate a static HTML report from a Jupyter notebook, run:python-mleda/path/to/nb.ipynb--output-dir./outputs/# Optional args:python-mleda/path/to/nb.ipynb--output-dir./outputs/\-i"abc = 123"-k"other_kernel"--cell-timeout100This generation automatically includes tweaks to the notebook to make
the output look more report-like (e.g., hiding all input code)See thestatic demosbeing served by GitHub Pages.ledais like:voila,
but static, with no need for live kernelsnbconvert/nbviewer, but with interactive widgetsquarto,
but with interactive widgetspapermill,
but with interactive widgetspretty-jupyter,
but with interactive widgetsThe-i(--inject) arg is used to inject user code (and set report params)
via a new cell prepended to the notebook during generation.And the--template_name/--themeargs allow you to choose betweenclassic,lab(light/dark), andlab_narrow(light/dark).Note:ledaassumes that all code is run in a trusted environment,
so please be careful.Interaction/Widgetsledaalso provides an%%interactmagicthat makes it easy to create outputs based on widgets that work in both dynamic
and static modes, e.g.:# In[ ]:importledaimportnumpyasnpimportpandasaspd# In[ ]:leda.init("matplotlib")# Loads `interact` magic when running in Jupyter notebook# In[ ]:%%interactcolumn=list("abcdefghij");mult=[1,2,3]df=pd.DataFrame(np.random.RandomState(42).rand(100,10),columns=list("abcdefghij"))title=f"column={column!r}, mult={mult}"(df[[column]]*mult).plot(figsize=(15,8),lw=2,title=title)There are two types of interact modes: dynamic and static.Dynamic modeis when you're running the Jupyter notebook
live, in which case you will re-compute the cell output
every time you select a differentmult. We always useipywidgetsas the
dynamic widget backend.In astatic mode(using whichever static widget backend is configured),
the library will pre-compute all possible combinations of widget outputs
(see Cartesian product)
and then render a static HTML report that contains widgets
that look and feel like the dynamic widgets (despite being pre-rendered).
See below for a list of supported static backends.Report Web UI ServerUnlikevoila,
because all report output isstatic HTML,
you can stand up a report web UI server that suits your needs very easily.
That means:It's trivial to set up in many cases.It's as scalable as your web server's ability to distribute static content.It's more cost-efficient because there are no runtimes whatsoever.You don't have to worry about old versions no longer working
due to code or data changes, so the historical
archive of old reports never expires or changes or breaks.For example, you can generate the report to a file,
upload that file to a shared location, and then stand
up a bare-bonesnginxserver to serve the files.
Instead of having a two-step process of generation + upload,
you could alternatively implement your ownleda.ReportPublisherand create a generation script of your own--or use it as a library
in client script.Another example is you can simply host a static S3 bucket,
enable website hosting and then either use S3 as a web server
publically or via locked down S3 endpoint.You could also useGitHub Pages,
much like thestatic demos page.ParamsReports can be parametrized so that the user can set
different values for each report run.In the notebook, just useleda.get_param():# In[ ]:importleda# In[ ]:data_id=leda.get_param("data_id",dynamic_default=1,static_default=2)And then change the injected code during each run:python-mleda/path/to/nb.ipynb--output./outputs/-i"data_id = 100"Modularledais built to work with multiple visualization and widget libraries.It works with these visualization libraries:matplotlibplotlyWith the default dynamic widget library:ipywidgetsAnd with these static widget libraries:static_ipywidgets(vendored and modified)panelTestingSee therequirements-bundle*.txtfor version bundles
that we currently test systematically.Known IssuesThere are multiple issues usingmatplotlibwithpanel, including:The last widget output is not different from the penultimate one:https://github.com/holoviz/panel/issues/1222All the widget outputs show up sequentially,
instead of being hidden until chosen.
This seems to be a known issue per thepanelFAQ;
however, using the example fix provided does not work.