IPython Widgets and Voila
From Notebook to Web-App with Voilà¶
Author: Marcel Baltruschat (@GitHub)
Date: 15.09.2022
License: MIT
Installation with Conda¶
conda create -n voila -c conda-forge python=3.10 voila jupyterlab pandas numpy rdkit ipywidgets plotly py3dmol
Imports¶
In [1]:
import io
import sys
import ipywidgets as widgets
import pandas as pd
import plotly
import plotly.graph_objects as go
import py3Dmol
import rdkit
import voila
from IPython.display import HTML, clear_output, display
from ipywidgets import interact, fixed
from rdkit.Chem import AllChem as Chem
Used Versions¶
In [2]:
print(f'Python: {sys.version.split("|")[0]}\nipywidgets: {widgets.__version__}\nPlotly: {plotly.__version__}\nRDKit: {rdkit.__version__}\npy3Dmol: {py3Dmol.__version__}\nVoilà: {voila.__version__}')
How to use Voilà?¶
There are two options to create a Voilà application.
- To run a notebook as a standalone application, in the commanline navigate to the directory that contains the notebook and then use the command
voila <path-to-notebook> <options>
. - To use Voilà as a Jupyter server extension on a running Jupyter notebook / lab server, go to the following URL:
<url-of-my-server>/voila
. For example, if Jupyter lab was running athttp://localhost:8888/lab
, then Voilà would be accessed athttp://localhost:8888/voila
.
Widget Examples¶
In [3]:
w = widgets.IntSlider()
w_frs = widgets.FloatRangeSlider(
value=[5, 7.5],
min=0,
max=10.0,
step=0.1,
description='Test:',
disabled=False,
continuous_update=False,
orientation='horizontal',
readout=True,
readout_format='.2f',
)
w_rb = widgets.RadioButtons(
options=['pepperoni', 'pineapple', 'anchovies'],
value='pineapple',
layout={'width': 'max-content'},
style={'description_width': 'initial'},
description='Pizza topping:',
disabled=False,
)
w_s = widgets.Dropdown(
options=['Linux', 'Windows', 'macOS'],
value='macOS',
description='OS:',
disabled=False,
)
In [4]:
accordion_s = widgets.Accordion(children=[w, w_frs])
accordion_s.set_title(0, 'Int slider')
accordion_s.set_title(1, 'Float range slider')
accordion_c = widgets.Accordion(children=[w_rb, w_s])
accordion_c.set_title(0, 'Radio buttons')
accordion_c.set_title(1, 'Dropdown selection')
tab = widgets.Tab(children=[accordion_s, accordion_c])
tab.set_title(0, 'Sliders')
tab.set_title(1, 'Selections')
tab
Example Plot¶
In [5]:
trace = go.Heatmap(z=[[1, 20, 30, 50, 1], [20, 1, 60, 80, 30], [30, 60, 1, -10, 20]],
x=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
y=['Morning', 'Afternoon', 'Evening'])
data = [trace]
layout = go.Layout(title='Activity Heatmap')
figure = go.Figure(data=data, layout=layout)
f2 = go.FigureWidget(figure)
f2
Display Molecules¶
Source: http://rdkit.blogspot.com/2016/07/using-ipywidgets-and-py3dmol-to-browse.html
In [6]:
def drawit(m, p, confId=-1):
mb = Chem.MolToMolBlock(m, confId=confId)
p.removeAllModels()
p.addModel(mb, 'sdf')
p.setStyle({'stick': {}})
p.setBackgroundColor('0xeeeeee')
p.zoomTo()
return p.show()
m = Chem.MolFromSmiles('COc1ccc2nc([nH]c2c1)[[email protected]](=O)Cc1ncc(C)c(OC)c1C')
m = Chem.AddHs(m)
Chem.EmbedMultipleConfs(m, numConfs=10, randomSeed=0xf00d, useExpTorsionAnglePrefs=True, useBasicKnowledge=True)
# align to one of the ring systems:
Chem.AlignMolConformers(m, m.GetSubstructMatch(Chem.MolFromSmarts('c1[nH]c2ccccc2n1')))
# now construct the view and interactive widget:
p = py3Dmol.view(width=400, height=400)
interact(drawit, m=fixed(m), p=fixed(p), confId=(0, m.GetNumConformers() - 1));
Display Proteins¶
In [7]:
view = py3Dmol.view(query='pdb:1hvr')
view.setStyle({'cartoon': {'color': 'spectrum'}})
view
Out[7]:
In [8]:
uploader = widgets.FileUpload(accept='csv', multiple=False)
button = widgets.Button(description='Show')
hbox = widgets.HBox((uploader, button))
output = widgets.Output()
vbox = widgets.VBox((hbox, output))
vbox
In [9]:
col_box = widgets.HBox()
col_box
In [10]:
df = None
def show_df(b):
with output:
clear_output()
try:
uploaded_file = uploader.value[list(uploader.value.keys())[0]]
global df
df = pd.read_csv(io.BytesIO(uploaded_file['content']), delimiter=';')
with output:
print(f'\nDataFrame size: {len(df)}. Showing first two lines:\n')
display(HTML(df.head(2).to_html()))
num_cols = [c for c, d in df.dtypes.items() if str(d).startswith('int') or str(d).startswith('float')]
col_menu = widgets.Dropdown(options=num_cols)
button2 = widgets.Button(description='Plot column values')
button2.on_click(show_plot)
col_box.children = (col_menu, button2)
except:
with output:
print('Please select a CSV file with ; as separator.')
button.on_click(show_df)
In [11]:
def show_plot(b):
col = col_box.children[0].value
trace = go.Histogram(x=df[col])
data = [trace]
layout = go.Layout(title=f'Histogram for column {col}')
figure = go.Figure(data=data, layout=layout)
plot_box.children = (go.FigureWidget(figure),)
In [12]:
plot_box = widgets.Box()
plot_box
References¶
In [ ]: