First we show the ability to set a workspace from Python:
class Workspace:
def __init__(self, workspace):
self.workspace = workspace
def _repr_mimebundle_(self, include=None, exclude=None):
return {
"application/x.jupyterlab.workspace+json": self.workspace
}
Click the button below to reload the page with the new workspace:
Workspace({
"ipywidgets:Demo.ipynb:c2fe7388d7fa4a8597d6f690a26f7ba9": {
"data": {
"data": {
"model_id": "c2fe7388d7fa4a8597d6f690a26f7ba9",
"version_major": 2,
"version_minor": 0,
},
"notebook": "Demo.ipynb",
}
},
"layout-restorer:data": {
"main": {
"dock": {
"type": "split-area",
"orientation": "vertical",
"sizes": [0.3756139489194499, 0.6243860510805501],
"children": [
{
"type": "tab-area",
"currentIndex": 0,
"widgets": ["notebook:Demo.ipynb"],
},
{
"type": "split-area",
"orientation": "horizontal",
"sizes": [0.5, 0.5],
"children": [
{
"type": "tab-area",
"currentIndex": 0,
"widgets": [
"application-mimedocuments:Demo.ipynb:JSON"
],
},
{
"type": "tab-area",
"currentIndex": 0,
"widgets": ["terminal:1"],
},
],
},
],
},
"mode": "multiple-document",
"current": "notebook:Demo.ipynb",
},
"left": {
"collapsed": True,
"widgets": [
"filebrowser",
"running-sessions",
"command-palette",
"tab-manager",
],
},
"right": {"collapsed": True, "widgets": []},
},
"notebook:Demo.ipynb": {"data": {"path": "Demo.ipynb", "factory": "Notebook"}},
"@jupyterlab/settingeditor-extension:plugin": {
"sizes": [0.11319534282018111, 0.8868046571798189],
"container": {
"plugin": "@jupyterlab/filebrowser-extension:browser",
"sizes": [0.4791970802919708, 0.5208029197080292],
},
},
"cloned-outputs:explorations/Untitled6.ipynb:17": {
"data": {"path": "explorations/Untitled6.ipynb", "index": 17}
},
"file-browser-filebrowser:cwd": {"path": ""},
"application-mimedocuments:tmp.json:JSON": {
"data": {"path": "tmp.json", "factory": "JSON"}
},
"application-mimedocuments:package.json:JSON": {
"data": {"path": "package.json", "factory": "JSON"}
},
"application-mimedocuments:Demo.ipynb:JSON": {
"data": {"path": "Demo.ipynb", "factory": "JSON"}
},
"terminal:1": {"data": {"name": "1"}},
})
<__main__.Workspace at 0x7ff198381be0>
Now we show the ablity to launch ipywidgets in new tabs. Click the button bellow to launch a new indows in JupyterLab with the widget:
class Widget:
def __init__(self, widget):
self.widget = widget
def _repr_mimebundle_(self, include=None, exclude=None):
return {
"application/x.jupyterlab.widget+json": {
'model_id': self.widget.model_id,
'version_major': 2,
'version_minor': 0,
}
}
import ipywidgets as widgets
items = [widgets.Label(str(i)) for i in range(5)]
left_box = widgets.VBox([items[0], items[1], items[4]])
right_box = widgets.VBox([items[2], items[3]])
w = widgets.HBox([left_box, right_box])
Widget(w)
<__main__.Widget at 0x7ff1680ce0d0>
We can combine our widget creating commands with our workspace commands and programatically generate workspaces that launch widgets in certain positions:
PATH = 'Demo.ipynb'
# area = widget or [orientation, sizes, areas]
def _output_widgets(area, data):
if isinstance(area, widgets.Widget):
model_id = area.model_id
key = f"ipywidgets:{PATH}:{model_id}"
data[key] = {
"data": {
"data": {
"model_id": model_id,
"version_major": 2,
"version_minor": 0
},
"notebook": PATH
}
}
return {"type": "tab-area", "currentIndex": 0, "widgets": [key]}
orientation, sizes, areas = area
return {
"type": "split-area",
"orientation": orientation,
"sizes": sizes,
"children": [_output_widgets(area, data) for area in areas]
}
def output_widgets(area):
data = {}
data["layout-restorer:data"] = {
"main": {
"dock": _output_widgets(area, data),
"mode": "multiple-document"
}
}
return Workspace(data)
This output_widgets
function takes in a recursive data structure to represent the layout you want to render, with widgets inside
!pip install matplotlib
Requirement already satisfied: matplotlib in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (3.1.3) Requirement already satisfied: cycler>=0.10 in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (from matplotlib) (0.10.0) Requirement already satisfied: numpy>=1.11 in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (from matplotlib) (1.18.1) Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (from matplotlib) (1.1.0) Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (from matplotlib) (2.4.6) Requirement already satisfied: python-dateutil>=2.1 in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (from matplotlib) (2.8.1) Requirement already satisfied: six in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (from cycler>=0.10->matplotlib) (1.14.0) Requirement already satisfied: setuptools in /usr/local/Caskroom/miniconda/base/envs/jupyter-widgets-takeover/lib/python3.8/site-packages (from kiwisolver>=1.0.1->matplotlib) (45.2.0.post20200210)
%matplotlib inline
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
def f(m, b):
plt.figure(2)
x = np.linspace(-10, 10, num=1000)
plt.plot(x, m * x + b)
plt.ylim(-5, 5)
plt.show()
interactive_plot = interactive(f, m=(-2.0, 2.0), b=(-3, 3, 0.5))
interactive_plot.children
output_widgets(
["horizontal", [0.3, 0.3, 0.4], [widgets.IntSlider(), widgets.ToggleButton(), ["vertical", [0.1, 0.1, 0.8], interactive_plot.children]]]
)
<__main__.Workspace at 0x7ff1784783a0>