Skip to content
Snippets Groups Projects
Commit 60e3e32f authored by alice grosch's avatar alice grosch
Browse files

Add content

parent 30e16241
Branches master
No related tags found
No related merge requests found
%% Cell type:markdown id:unable-wisconsin tags:
%% Cell type:markdown id:binary-seafood tags:
# Advantages and Disadvantages of Voilà
When should you use Voilà? What are Voilà apps suitable for? And when should you rather use something else (like Dash apps)?
%% Cell type:markdown id:unable-prefix tags:
%% Cell type:markdown id:pharmaceutical-campus tags:
# Use Voilà when...
**...you already use Jupyter Notebooks.** If it works in Jupyter, it works in Voilà! Voilà is Jupyter native and part of its core ecosystem. It makes converting your Jupyter notebooks into stand-alone interactive web-based dashboard applications easy, enabling a smooth transition from the exploratory phase of data analysis to the communication of the resulting data insights. You can test and explore through Notebooks and serve with Voilà for dashboarding.
**...you need to provide secure and authorized access to data on HPC (or other) systems.** There are two scenarios which are imaginable here:
1. **You share the `.ipynb` file and the user has to run the `voila` command themselves.**
Not a great solution. Mostly suitable when you want to share an exploratory dashboard amongst your team.
2. **You only let users start the Voilà dashboard, they never see the actual Notebook file.**
You can create a dashboard with relies on large data sets on a HPC system and share it with other people as long as they have access to the same HPC system. At the same time, they cannot run arbitrary code to gain unauthorized access to the systems (for example, they cannot run their own code under your account) or accidentally modify your data.
If you have acces to cloud computing resources and are able make your data available on the cloud, you can also share your notebook without the other person needing access to any HPC system.
So, how do we accomplish that?
%% Cell type:markdown id:transparent-payroll tags:
%% Cell type:markdown id:prerequisite-cartridge tags:
## Excursion: JupyterHub
### What is JupyterHub?
With [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) you can create a multi-user Hub which spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server.
Basic principles for operation are:
* Hub launches a proxy.
* Proxy forwards all requests to Hub by default.
* Hub handles login (includes authentication), and spawns single-user servers on demand.
* Hub configures proxy to forward URL prefixes to the single-user notebook servers.
![JupyterHub subsytems](img/jhub-parts.png)
### Example: JupyterHub at JSC - jupyter-jsc.fz-juelich.de
![JupyterHub at JSC](img/jupyterhub-jsc.png)
## JupyterHub and Voilà
Instead of launching a single-user notebook server, configure JupyterHub to directly launch a voila server instead. That way, the user never sees the Jupyter interface and does not get any access to the system. Remember: Voilà runs the notebook once and disallows all further execute requests.
You can configure your dashboard to only run on certain systems. For example, your Voilà dashboard is allowed to run on JUWELS, but not JURECA. If you launch Voilà dashboard on the Cloud, even users without access to the HPC systems can run your dashboard.
%% Cell type:markdown id:sexual-serum tags:
Another possible way, with which I however don't have personal experience, seems to be [ContainDS Dashboards for JupyterHub](https://github.com/ideonate/cdsdashboards):
> Run a private on-premise or cloud-based JupyterHub with extensions to instantly publish apps and notebooks as user-friendly interactive dashboards to share with non-technical colleagues.
%% Cell type:markdown id:alone-december tags:
# Disadvantages of Voilà
However...
**...Voilà does not scale very well.** Voila must have at least one process/thread per session which must live for as long as the user wishes to interact. Depending on use case, starting a new kernel each time can lead to large overheads and memory consumption.
In addition, a user's session is intimately tied to this process (with at least some state being stored there) and the user cannot be moved between machines without ‘starting again’. This makes horizontal scaling and caching much harder. It also adds a responsibility on the server to manage and kill processes that aren’t being used anymore. This can easily be misjudged, killing processes that are still desired or leaving live processes that aren't being used.
**...Voilà has limited design flexibility.** It is not always straightforward to control the intricacies regarding the application layout and appearance. And although there are a handful of useful templates, outside of these templates the only option is to construct your own nbconvert templates.
**...Voilà does not support multi-page applications.** There are some workarounds, but nothing really akin to a true multi-page applications.
**...Voilà does not natively support user authentication.**
%% Cell type:markdown id:defensive-discharge tags:
%% Cell type:markdown id:separate-controversy tags:
# Alternatives?
# Closest Alternative?
[Panel](https://panel.holoviz.org/index.html) is similar to Voilà and very well integrated with Jupyter Notebooks, although you don't need to use Notebooks at all. Panel is built on top of Bokeh widgets and server. You only need Python to get started (in fact, Panel only supports Python), although HTML, CSS and JavaScript knowledge is helpful for styling your dashboard. It supports all Python plotting libraries and has enhanced support for Bokeh and Plotly.
The syntax of Panel is similar to that of `ipywidgets`. Most concepts should be familiar, although the actual syntax might differ. The [Documentation](https://panel.holoviz.org/user_guide/index.html) is excellent if you want to learn how to use Panel. There is also an [example gallery](https://panel.holoviz.org/gallery/index.html) you can check out to see what is possible with Panel.
**What Panel does differently:**
* Panel explicitly supports multi-page applications, and can do so in multiple different ways — such as using `Tabs`, `Pipelines`, and `Templates`. Panel enables sharing of state between application pages, leading to the creation of complex multi-page applications.
* Panel offers great design flexibility. It is easy to use for straightforward data dashboard applications, but there are various templates, inline HTML & CSS, inclusion of external CSS and JavaScript files, and the ability to create your own templates to spice up your dashboard. But as you can imagine, it can be quite tricky once you get past more trivial dashboard interfaces.
* Panel also includes out-of-the-box authentication with OAuth 2.0.
* Panel lets you can have multiple users per process and therefore cache data/computation across multiple sessions. This means that in many cases the per user overhead is (or can be) much smaller when compared to starting an entirely new kernel (i.e. <1 MB vs 100+ MB).
**When to use Panel:**
* You can use Panel if you already use Jupyter Notebooks and want more flexibility than what is offered by Voila.
* With Panel, it is easy to create dashboards which are not restricted to a single GUI.
* Panel ist best suited for dealing with gridded and geospatial data.
%% Cell type:code id:shared-aspect tags:
**Panel vs Voilà:**
* Voila - Rapid prototyping in Jupyter notebooks. Quickly and reliably report data insights across an organisation.
* Panel - Creating dashboard applications not restricted to a single GUI. Working with geospacial data.
%% Cell type:code id:threatened-carroll tags:
``` python
```
......
%% Cell type:code id:leading-montana tags:
%% Cell type:markdown id:molecular-function tags:
``` python
```
# Multi-Page Apps and URL Support
See https://dash.plotly.com/urls.
......
%% Cell type:markdown id:comfortable-inclusion tags:
%% Cell type:markdown id:elect-touch tags:
https://datasciencecampus.github.io/deploy-dash-with-gcp/
# Deploying your Dash app
https://austinlasseter.medium.com/deploying-a-dash-app-with-elastic-beanstalk-console-27a834ebe91d
Here is the official documentation on deploying Dash: https://dash.plotly.com/deployment
It's, again, very heavy on Dash Enterprise, but does contain a section on how to share your Dash app on Heroku.
kubernetes
https://ldnicolasmay.medium.com/deploying-a-free-dash-open-source-app-from-a-docker-container-with-gunicorn-3f426b5fd5df
Dash apps can be deployed on any servers which support Flask app deployment. Here are some more tutorials on how to deploy dash on other platforms:
https://towardsdatascience.com/build-a-highly-scalable-dashboard-that-runs-on-kubernetes-fa2bc6271f1d
* [Heroku](https://towardsdatascience.com/deploying-your-dash-app-to-heroku-the-magical-guide-39bd6a0c586c)
* [Google Cloud Platform](https://datasciencecampus.github.io/deploy-dash-with-gcp/)
* [Google App Engine](https://www.phillipsj.net/posts/deploying-dash-to-google-app-engine/)
* [AWS Elastic Beanstalk](https://austinlasseter.medium.com/deploying-a-dash-app-with-elastic-beanstalk-console-27a834ebe91d)
* [Azure](https://www.phillipsj.net/posts/deploying-dash-to-azure-without-using-docker/)
* [PythonAnywhere](https://towardsdatascience.com/the-easiest-way-to-deploy-your-dash-app-for-free-f92c575bb69e)
* Kubernetes
* [Docker container and gunicorn](https://ldnicolasmay.medium.com/deploying-a-free-dash-open-source-app-from-a-docker-container-with-gunicorn-3f426b5fd5df)
* [Using Python, Docker and Google Cloud Platform](https://towardsdatascience.com/build-a-highly-scalable-dashboard-that-runs-on-kubernetes-fa2bc6271f1d)
%% Cell type:markdown id:acknowledged-genealogy tags:
%% Cell type:code id:hearing-sunrise tags:
https://appsilon.com/overview-of-dash-python-framework-from-plotly-for-building-dashboards/
``` python
```
......
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import flask
app = dash.Dash(__name__)
url_bar_and_content_div = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
layout_index = html.Div([
dcc.Link('Navigate to "/page-1"', href='/page-1'),
html.Br(),
dcc.Link('Navigate to "/page-2"', href='/page-2'),
])
layout_page_1 = html.Div([
html.H2('Page 1'),
dcc.Input(id='input-1-state', type='text', value='Montreal'),
dcc.Input(id='input-2-state', type='text', value='Canada'),
html.Button(id='submit-button', n_clicks=0, children='Submit'),
html.Div(id='output-state'),
html.Br(),
dcc.Link('Navigate to "/"', href='/'),
html.Br(),
dcc.Link('Navigate to "/page-2"', href='/page-2'),
])
layout_page_2 = html.Div([
html.H2('Page 2'),
dcc.Dropdown(
id='page-2-dropdown',
options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
value='LA'
),
html.Div(id='page-2-display-value'),
html.Br(),
dcc.Link('Navigate to "/"', href='/'),
html.Br(),
dcc.Link('Navigate to "/page-1"', href='/page-1'),
])
# index layout
app.layout = url_bar_and_content_div
# "complete" layout
app.validation_layout = html.Div([
url_bar_and_content_div,
layout_index,
layout_page_1,
layout_page_2,
])
# Index callbacks
@app.callback(Output('page-content', 'children'),
Input('url', 'pathname'))
def display_page(pathname):
if pathname == "/page-1":
return layout_page_1
elif pathname == "/page-2":
return layout_page_2
else:
return layout_index
# Page 1 callbacks
@app.callback(Output('output-state', 'children'),
Input('submit-button', 'n_clicks'),
State('input-1-state', 'value'),
State('input-2-state', 'value'))
def update_output(n_clicks, input1, input2):
return ('The Button has been pressed {} times,'
'Input 1 is "{}",'
'and Input 2 is "{}"').format(n_clicks, input1, input2)
# Page 2 callbacks
@app.callback(Output('page-2-display-value', 'children'),
Input('page-2-dropdown', 'value'))
def display_value(value):
print('display_value')
return 'You have selected "{}"'.format(value)
if __name__ == '__main__':
app.run_server(debug=True)
\ No newline at end of file
import dash
import dash_core_components as dcc
import dash_html_components as html
# Since we're adding callbacks to elements that don't exist in the app.layout,
# Dash will raise an exception to warn us that we might be
# doing something wrong.
# In this case, we're adding the elements through a callback, so we can ignore
# the exception.
app = dash.Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
index_page = html.Div([
dcc.Link('Go to Page 1', href='/page-1'),
html.Br(),
dcc.Link('Go to Page 2', href='/page-2'),
])
page_1_layout = html.Div([
html.H1('Page 1'),
dcc.Dropdown(
id='page-1-dropdown',
options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
value='LA'
),
html.Div(id='page-1-content'),
html.Br(),
dcc.Link('Go to Page 2', href='/page-2'),
html.Br(),
dcc.Link('Go back to home', href='/'),
])
@app.callback(dash.dependencies.Output('page-1-content', 'children'),
[dash.dependencies.Input('page-1-dropdown', 'value')])
def page_1_dropdown(value):
return 'You have selected "{}"'.format(value)
page_2_layout = html.Div([
html.H1('Page 2'),
dcc.RadioItems(
id='page-2-radios',
options=[{'label': i, 'value': i} for i in ['Orange', 'Blue', 'Red']],
value='Orange'
),
html.Div(id='page-2-content'),
html.Br(),
dcc.Link('Go to Page 1', href='/page-1'),
html.Br(),
dcc.Link('Go back to home', href='/')
])
@app.callback(dash.dependencies.Output('page-2-content', 'children'),
[dash.dependencies.Input('page-2-radios', 'value')])
def page_2_radios(value):
return 'You have selected "{}"'.format(value)
# Update the index
@app.callback(dash.dependencies.Output('page-content', 'children'),
[dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/page-1':
return page_1_layout
elif pathname == '/page-2':
return page_2_layout
else:
return index_page
# You could also return a 404 "URL not found" page here
if __name__ == '__main__':
app.run_server(debug=True)
\ No newline at end of file
04_plotly_dash/img/comparison.jpeg

172 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment