Thebe¶
Get started¶
In order to use Thebe, you must take the following steps on a page:
Load the thebe javascript bundle¶
The Thebe Javascript is most-easily obtained from a CDN. You can load the javascript library from a CDN by including this on a page:
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Alternatively, you can download the bundle and include it along with your site.
Configure Thebe in your page’s HTML¶
Thebe looks for a specific HTML block for its configuration. This happens when Thebe is “bootstrapped” (i.e., launched).
The configuration block has the following structure:
<script type="text/x-thebe-config">
{
a: collection
of: key
val: pairs
}
</script>
See Configure Thebe for information about how and what to configure with Thebe.
Bootstrap Thebe on the page¶
If the Thebe Javascript bundle is loaded, and the configuration file is present, you may bootstrap (i.e., launch) Thebe by calling the following Javascript function:
thebelab.bootstrap()
This will take one or more of the following actions:
Re render the code cells to make them live cells. (the rendering can handle cells that contain a mixture of inputs and ouputs distinguished by prompts)
(optional) Request a notebook server from Binder
(optional) Request a Jupyter kernel from a notebook server.
Calling the bootstrap function is generally accomplished by connecting it to the “click” event of a button on the page.
Tip
If bootstrap: true
is in the Thebe configuration, this will be triggered
automatically upon page load.
Configure Thebe¶
You control Thebe’s behavior with a configuration block that is placed somewhere in a page’s HTML. The block has the following structure:
<script type="text/x-thebe-config">
{
a: collection
of: key
val: pairs
}
</script>
For example, the following configuration tells Thebe to use a BinderHub for its sessions, as well as the repository to use with Binder:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "binder-examples/requirements",
ref: "master",
},
}
</script>
When Thebe is launched on a page, this configuration is used to control its behavior.
See the sections below for things that you can control with Thebe configuration.
Configure the kernel that will be launched¶
To configure the kernel that Thebe requests when it launches, use the following section in the Thebe configuration:
kernelOptions: {
kernelName: "python3",
},
When Thebe is launched, it will request a kernel of this name for the page. Note that currently there can be only one kernel per page.
Note
You must ensure that the value of kernelName
exists in the environment that
Thebe tries to launch. Some short-hands for certain languages (like python
)
may also work.
Configure the working directory of the launched kernel¶
In addition to choosing the kernel, you may also choose the path where the kernel is launched. This will be relative to the root of the launched Jupyter server (e.g., if using a BinderHub, this will be relative to the root of the repository).
To configure the path of the working directory, use the following configuration:
kernelOptions: {
kernelName: "python3",
path: "path/to/directory"
}
Customize CodeMirror¶
CodeMirror is the tool used to convert your code cells into editable cells. It has a number of configuration options, such as theming and syntax highlighting. You can edit all of these attributes in a cell with the following thebe configuration:
// Additional options to pass to CodeMirror instances
codeMirrorConfig: {},
You can use any of the available CodeMirror configurations. For example, the following configuration changes the CodeMirror theme:
codeMirrorConfig: {
theme: "abcdef"
}
The below code cell demonstrates this theme:
%matplotlib inline import numpy as np import matplotlib.pyplot as plt plt.ion() fig, ax = plt.subplots() ax.scatter(*np.random.randn(2, 100), c=np.random.randn(100)) ax.set(title="Wow, an interactive plot!")
The above code should be styled according to the CodeMirror abcdef theme.
Mark a code cell as read-only¶
If you would like a code cell to be runnable by Thebe, but not editable by the user, you may mark it as “read-only” with the following syntax:
<pre data-executable data-readonly>print("I cannot be modified")</pre>
Users will not be able to modify the code once Thebe is activated, though they can still press the “run” button to see the outputs.
To set all cells as read-only by default, use the following thebe
configuration:
codeMirrorConfig: {
readOnly: true
}
This uses codeMirror to mark all cells as read-only. If you are using this setting and would like to
manually mark individual cells as editable, you can override the codeMirror configuration for a cell using data-readonly="false"
. For example:
<pre data-executable data-readonly="false">print("I still can be modified")</pre>
<pre data-executable>print("Due to codeMirrorConfig, I cannot be modified")</pre>
Security Considerations¶
Thebe allows users to run arbitrary code both in Python and, potentially, in Javascript. This allows interactive figures, and custom outputs to be run in your documentation, which is the benefit that Thebe brings! ✨
Cross Site Scripting¶
However, this can also lead to Cross-Site Scripting (XSS) attacks, with the most likely case being an Self-XSS attack. This happens when someone executes code that they do not understand, or is malicious.
For example, the %%html
and the %%javascript
cell-magics in Jupyter can directly insert
script tags into your page. They can potentially modify the DOM, make API calls on the users behalf,
or run untrusted code.
We recommend that you run Thebe in a static environment (e.g. ReadTheDocs or similar) that has no access to user credentials such as cookies or API keys.
Event hooks in Thebe¶
When Thebe is launched (with thebelab.bootstrap
), it will emit a series
of events corresponding to the state of the launch process. You can plug into
these events to control the behavior on your page.
To do so, use the status
event within Thebe, like so:
thebelab.on("status", function (evt, data) {
console.log("Status changed:", data.status, data.message);
});
In the above code, the data
object contains a collection of information about
Thebe, and data.status
will reflect the current state of Thebe. This will
cycle between these states:
building
built
launching
ready
These events can be used to do things like running code once the Jupyter Kernels is ready, or manipulating the page DOM before launching Thebe to result in certain behavior (e.g. a “loading status” button).
Configuration Reference¶
Here is an example of all possible configuration
options for Thebe. This is what you place in between the
<script type="text/x-thebe-config">
HTML tags on your page.
{
// Whether thebe should automatically trigger the bootstrap upon page load
// if set to false, the page should contain some additional javascript
// responsible for triggering the javascript when desired (e.g. connected to a button click).
bootstrap: false,
// arbitrary pre-render function called as part of bootstrap
preRenderHook: false,
// Whether to request the kernel immediately when thebe is bootstrapped
// instead of on executing code for the first time
requestKernel: false,
// Whether thebe should look for predefined output of cells before execution
// If this option is enabled and the next div after the cell has the attribute
// data-output=true (default), then the content of this div is rendered as output
predefinedOutput: false,
// The selector for identifying whether an element should be treated as output
outputSelector: '[data-output]',
// Options for requesting a notebook server from mybinder.org
binderOptions: {
repo: "minrk/ligo-binder",
// only repo is required, the rest below are defaults:
ref: "master",
binderUrl: "https://mybinder.org",
// select repository source (optional). Supports Github(default), Gitlab, and Git
repoProvider: "github",
savedSession: {
// if enabled, thebe will store and try to re-use
// connections (with credentials!) to running servers
enabled: true,
maxAge: 86400, // the max age in seconds to consider re-using a session
storagePrefix: "thebe-binder-",
}
},
// Options for requesting a kernel from the notebook server
kernelOptions: {
name: "python3",
kernelName: "python3",
path: "."
// notebook server configuration; not needed with binder
// serverSettings: {
// "baseUrl": "http://127.0.0.1:8888",
// "token": "test-secret"
// }
},
// Selector for identifying which elements on the page should
// be made interactive
selector: "[data-executable]",
// Optional prompt handling during the rendering phase
// Either false or a dictionary as in the example below
stripPrompts: false,
// stripPrompts: {
// inPrompt: 'sage: ',
// continuationPrompt: '....: ',
// // only apply the prompt stripping to cells matching this selector (optional)
// selector: '.sage-input',
// },
// URL from which to load mathjax
// set to `false` to disable mathjax
mathjaxUrl: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js",
// mathjax configuration string
mathjaxConfig: "TeX-AMS_CHTML-full,Safe",
// Additional options to pass to CodeMirror instances
codeMirrorConfig: {},
}
Running cells when Thebe starts¶
Sometimes it is helpful to automatically run some cells when Thebe starts. For example, if you’d like to pre-define some variables or import a function that you’ll use later on. This lets you focus the code that users read on the ideas that you want to convey.
Thebe can be controlled via Javascript after it has been initialized. Below are two ways that you can configure your Javascript to run code under-the-hood.
Running cells when Thebe is initialized¶
A straightforward way to run code is to simply simulate a click on the buttons that
are created when you launch Thebe. By selecting the Thebe button and calling
the click()
method, the code in that cell will be run (and outputs will show)
once the Thebe kernel is ready.
Here’s a code sample that selects all cells with a tag called thebelab-init
and
simulates a click on the button.
thebelab.events.on("request-kernel")(() => {
// Find any cells with an initialization tag and ask Thebe to run them when ready
var thebeInitCells = document.querySelectorAll('.thebelab-init');
thebeInitCells.forEach((cell) => {
console.log("Initializing Thebe with cell: " + cell.id);
const initButton = cell.querySelector('.thebelab-run-button');
initButton.click();
});
});
Running custom code with Thebe¶
In addition, you can run your own custom code from the Thebe object with
Javascript using the requestExecute
method. Below is a code snippet that
uses the same event trigger, but in this case runs some custom code against the kernel
once it is ready.
thebelab.events.on("request-kernel")((kernel) => {
// Find any cells with an initialization tag and ask Thebe to run them when ready
kernel.requestExecute({code: "import numpy"})
});
In both of the cases above, you’ll likely need to customize the Javascript calls depending on how your code is structured and what behavior you’d like when users land on a page.
Contributing Guide¶
Thanks for your interest in contributing to thebe
, your contributions are welcome and appreciated 🎉. This page contains some information to help you get started.
Note
thebe
was recently called thebelab
, so you may see mentions of thebelab
scattered throughout the repository. Feel free to flag these and suggest we rename them to thebe
.
Contributing guide¶
See the ExecutableBooks developer guidelines for conventions and practices around developing thebe
. However, note that some practices, such as creating releases, may be different because thebe
is primarily an Javascript (npm
) package rather than a Python package.
Repository structure¶
thebe
is primarily written in Javascript, and structured as an NPM package.
src/
contains the code and assets that make upthebe
. This is what you’ll edit to make changes to the project.examples/
provides a few HTML examples of howthebe
can be used. It is mostly for documentation
Set up a development environment¶
In order to get Thebe running locally, you’ll need to have Node installed on your system.
Minimum requirements are:
nodejs v15.0 or greater
npm v6.0 or greater
yarn v1.22 or greater
You can install it in several ways, the most common being:
Install Node by following the nodejs instructions
Using the node version manager
Install Node through
conda
conda install -c conda-forge nodejs
Once installed, also install yarn
which is what you will run in order to run Thebe locally.
npm install -g yarn
Next, clone the repository and install the required dependencies:
git clone https://github.com/executablebooks/thebe
cd thebe
yarn install
This will install all dependencies needed to run thebe
(specified in package.json
). By default, yarn install
will also have created a production build in lib
If you are using npm
v7 you may encounter Peer Dependency Errors see comments below to resolve these.
Note
Using yarn install
will ensure that you install the latest tested dependencies, and will not make any unintentional local upgrades. yarn
uses npm
under the hood, please do not use npm install
directly to install dependencies.
Peer Dependency Errors¶
Due to recent changes in npm
as of v7 peer dependency issues are flagged as critical errors. However, many projects have not yet resolved these issues in their code base, this means that a project’s co-dependencies can prevent installation of a package. This is a know issue, to resolve this there are two options:
Downgrade
npm
to v6
npm install -g npm@6
Set the
legacy-peer-deps
option in your local environment
npm config set legacy-peer-deps true
Build and demo thebe
locally¶
To use your local copy of thebe
(e.g., if you make any changes to the src/
folder), you can run a local build and serve a sample web page. To do so, run:
yarn run build:watch
This will build thebe/
locally (including any changes you’ve made to the source code).
You can now demo the latest thebe/
changes by opening the file at development/binder.html
. Open this file to see Thebe running.
The content of development/binder.html
is a simple HTML page that demonstrates Thebe functionality. You can edit it to test out new features or configurations.
Running the yarn run develop
command will start a watch on the source code, building with webpack and will serve it along with development/binder.html
.
As you change the code in src/
, the javascript will automatically be re-built, but you’ll be required to refresh the page.
Using a local kernel¶
development/binder.html
will connect to a public binder instance which can be slow.
For faster development and easy control over the python environment available to Jupyter is run yarn run develop:local
instead.
This will serve the file from development/local.html
which will attempt to connect to a local Jupyter kernel.
You will need to have Jupyter running with the expected authentication token for this to work. i.e.
jupyter notebook \
--NotebookApp.token=thebe-test-secret \
--NotebookApp.allow_origin='http://127.0.0.1:8080'
Committing changes¶
Thebe uses code autoformatting so you don’t need to worry about style lint,
so whenever you are ready to commit changes
run yarn run fmt
to autoformat the javascript.
You can put this script in .git/hooks/pre-commit
:
#!/bin/sh
if [[ -f package.json ]]; then
yarn run fmt
fi
to run auto-formatting prior to each commit.
Testing Thebe¶
You can test manually, interactively by running yarn run develop
to open and serve development.html
with the current build of thebe.
Running automated tests¶
There are two types of automated test environment in place in thebe both using the Jest testing library. These are:
a standard javascript testing setup for unit / component level testing of the thebe library. These can be run using
yarn run test
oryarn run test:watch
and test code is located in thetest
folder.e2e style tests using jest + puppeteer that can be run
yarn run test:e2e
oryarn run test:e2e:watch
and test code is located in thee2e
folder.
Alternately, you can push your changes to GitHub and let the tests run automatically via GitHub Actions.
TODO: get testing infrastructure to a point where we can reasonably request tests for new features.
Adding unit tests¶
Unit style tests work by loading the thebe library or part of it in javascript; mocking inputs and/or dependencies, executing a function and asserting on outputs of mocks. A good first example to look at is tests/bootstrap.spec.js
. This test:
loads thebe js code
import * as thebelab from "../src/thebelab";
manipulates the dom to prep the test (via built in JSDOM)
calls the
thebe.bootstrap()
functionchecks for expected behaviour
If you are new to Jest check their getting started, mocking and expect assertion api docs.
Adding e2e Tests¶
e2e style tests are achieved using Puppeteer a headless chrome api that can be used to load a page complete with thebe scripts, allowing full execution as though it was in an end user browser and then assertion of end state.
Adding new e2e tests involves:
(see e2e/readonly.test.js
for an example)
creating a test html page that load and uses thebe, placing this in the
e2e/fixtures/HTML
folderload the fixture page at the start of your test
beforeAll(async () => {
await page.goto(
`file:${path.join(__dirname, "/fixtures/HTML/readonly1.html")}`,
{ waitUntil: ["load", "domcontentloaded", "networkidle0"] }
);
});
Assert on initial page state
Invoke UI actions to trigger behavior
assert on final state
Building docs locally¶
Thebe uses Sphinx and JupyterBook for building documentation. Thebe documentation is located in the /docs
directory.
You will need the development environment setup, see the above Set up a development environment to learn more.
You will also need Python installed, and can install the requirements for the documentation using:
cd docs/
pip install -r doc-requirements.txt
Once you are in the documentation folder:
make html
Finally, run the following to view the built documentation locally:
make show
Releasing Thebe¶
To release thebe, follow the EBP guidelines to make sure the repo is ready for release.
Once prepared, bump the version with:
Use yarn to update the thebe version in the
package.json
file and to create a git tag for the version usingyarn version --new-version NEW_VERSION
, e.g.yarn version --new-version 0.5.1
Push the tag to github:
git push --follow-tags
Create a release for the new tag on github at https://github.com/executablebooks/thebe/releases/new; this will trigger a github action that uploads the latest version to unpkg.com/browse/thebe/.
Thebe architecture¶
Thebe consumes three principal APIs:
jQuery for manipulating elements on the page
JupyterLab for talking to a running Jupyter server to execute code and display outputs
BinderHub for requesting kernels from a BinderHub instance, such as mybinder.org.
Manipulating the page¶
The first thing Thebe does is find elements on the page
that should be made executable.
It does this with jQuery,
finding (by default) elements that look like <div data-executable="true">...
,
with a query such as the $("[data-executable])
(this is the default, but can be customized).
Once it has found these elements,
Cell objects are created (more on Cells in the JupyterLab API), which then replace the elements that were found.
JupyterLab APIs¶
The main thing Thebe does is execute code and display output. This is done with JupyterLab APIs. A Cell is an element wrapping a code input area and associated OutputArea for displaying the outputs that result from execution.
Main APIs used:
OutputArea for rendering outputs on the page
Session for starting kernels
Kernel for sending/receiving messages to/from a connected kernel
WidgetManager for working with interactive widgets
Configuration¶
Configuration is handled by adding a script
tag with type=”text/x-thebe-config”. This should specify a javascript object.
More information in the README (TODO: move it here?)
<script type="text/x-thebe-config">
{
binderOptions: {
repo: "minrk/ligo-binder",
ref: "master",
}
}
</script>
thebe API¶
The thebe JavaScript API
Note
This document is a work in progress. We need to add jsdoc-style docstrings to our exported functions.
-
bootstrap
(options)¶ Do it all in one go. 1. load options 2. run hooks 3. render cells 4. request a Kernel 5. hook everything up
- Arguments
options (Object) – Object containing thebe options. Same structure as x-thebe-options.
- Returns
Promise – Promise for connected Kernel object
Thebe turns your static HTML pages into interactive ones, powered by a kernel. It is the evolution of the original Thebe project with javascript APIs provided by JupyterLab.
For example, see the following code cell:
%matplotlib inline import numpy as np import matplotlib.pyplot as plt plt.ion() fig, ax = plt.subplots() ax.scatter(*np.random.randn(2, 100), c=np.random.randn(100)) ax.set(title="Wow, an interactive plot!")
It is static for now. You can activate Thebe by pressing the button below. This will ask mybinder.org for a Python kernel, and turn the code cell into an interactive one with outputs!
Try clicking the button. The cell will be come active!
You can press “run” in order to run the contents of the cell and display the result (be patient, it will take a few moments for Binder to start the kernel).
Getting Started¶
To get started, check out Get started.
Examples¶
For more examples showing how to configure, use, and activate Thebe, see the list below. We recommend browsing the raw HTML of each one in order to see how Thebe is used.
A minimal example¶
This page illustrates a minimal setup to get Thebe running, using mybinder as a kernel (i.e. computation backend) provider. This guide will go step-by-step in loading Thebe and activating it so that your code cells become active.
Loading and configuring Thebe¶
In order to use Thebe, we must first set its configuration. This must be done before Thebe is loaded from a CDN or a local script.
Here’s a sample configuration for Thebe
<!-- Configure and load Thebe !-->
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "binder-examples/requirements",
},
}
</script>
In this case, requestKernel: true
asks Thebe to request a kernel
immediately upon being loaded, and binderOptions
provides the repository
that Binder will use to give us a Kernel.
Next, we’ll load Thebe from a CDN:
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Adding a button to activate Thebe¶
There are many ways you can activate Thebe. In this case, we’ll add a button to our page, and configure it to bootstrap Thebe once it is clicked. We’ll do this with a little bit of Javascript.
Placing the button and adding the JavaScript to enable Thebe was done with the code below:
<button id="activateButton" style="width: 150px; height: 75px; font-size: 1.5em;">Activate</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Adding code cells¶
Finally, we’ll add code cells that Thebe can activate. By default, Thebe
will look for any HTML elements with data-executable="true"
. We’ll also add
a data-language="python"
attribute to enable syntax highlighting with CodeMirror.
print("Hello!")
Here’s the code that created the cell above:
<pre data-executable="true" data-language="python">print("Hello!")</pre>
Press the Thebe button above to activate this cell, then press the “Run” button, or “Shift-Enter” to execute this cell.
Note
When Thebe is activated in this example, it must first ask Binder for a kernel. This may take several seconds.
Now let’s try another cell that generates a Matplotlib plot. Because we’ve configured Thebe to use Binder with an environment that has Numpy and Matplotlib, this works as expected. Try modifying the cell contents and re-running!
This is another cell, with plotting. Shift-Enter again!
%matplotlib inline import numpy as np import matplotlib.pyplot as plt x = np.linspace(0,10) plt.plot(x, np.sin(x)) plt.plot(x, np.cos(x))
Here’s the HTML for the cell above:
<pre data-executable="true" data-language="python">
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10)
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))
</pre>
And here’s an example where the contents cannot be modified once instantiated:
print("My contents cannot be changed!")
For more examples, check out Examples.
Bqplot Example¶
Thebe can display output from bqplot Jupyter widgets, a 2D plotting library. This example is repurposed from the bqplot documentation and is licensed under the Apache License 2.0 License. Note that this example does not fix the pan/zoom feature on plots.
Setup¶
Be sure to load require.min.js and Font Awesome 4 before any of your thebe activation code, it is required for the bqplot widget and navigation icons to work:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
Configure thebe and load it:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "bqplot/bqplot",
ref: "0.12.18",
binderUrl: "https://mybinder.org",
repoProvider: "github",
},
}
</script>
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Create a button to activate thebe:
<button id="activateButton" style="width: 120px; height: 40px; font-size: 1.5em;">
Activate
</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Now add code cells between these HTML tags:
<pre data-executable="true" data-language="python"></pre>
Example¶
Press the “Activate” button below to connect to a Jupyter server:
Here we will display a basic 2D plot:
import numpy as np from bqplot import pyplot as plt size = 100 np.random.seed(0) x_data = np.arange(size) y_data = np.cumsum(np.random.randn(size) * 100.0) plt.figure(title='My First Plot') plt.plot(x_data, y_data) plt.show()
Ipyleaflet Example¶
Thebe can display output from ipyleaflet Jupyter widgets. This example is repurposed from the ipyleaflet documentation and is licensed under the MIT License (MIT).
Setup¶
Be sure to load require.min.js before any of your thebe activation code, it is required for Jupyter widgets to work:
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
Configure thebe and load it:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "jupyter-widgets/ipyleaflet",
ref: "0.13.3",
binderUrl: "https://mybinder.org",
repoProvider: "github",
},
}
</script>
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Create a button to activate thebe:
<button id="activateButton" style="width: 120px; height: 40px; font-size: 1.5em;">
Activate
</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Now add code cells between these HTML tags:
<pre data-executable="true" data-language="python"></pre>
Example¶
Press the “Activate” button below to connect to a Jupyter server:
Here we will display a basic leaflet map:
from ipyleaflet import Map, Heatmap from random import uniform import time def create_random_data(length): "Return a list of some random lat/lon/value triples." return [[uniform(-80, 80), uniform(-180, 180), uniform(0, 1000)] for i in range(length)] m = Map(center=[0, 0], zoom=2) m
Now we add a heatmap:
heat = Heatmap(locations=create_random_data(1000), radius=20, blur=10) m.add_layer(heat)
Finally, we add some animation to our heatmap:
for i in range(100): heat.locations = create_random_data(1000) time.sleep(0.1)
Ipympl Example¶
Thebe can display output from ipympl, which enables interactivity with matplotlib.
Setup¶
Be sure to load require.js and Font Awesome 4 before any of your thebe activation code so that the matplotlib widgets can function.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
Configure thebe and load it:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "matplotlib/ipympl",
ref: "0.6.1",
repoProvider: "github",
},
}
</script>
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Create a button to activate thebe:
<button id="activateButton" style="width: 120px; height: 40px; font-size: 1.5em;">
Activate
</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Now add between these HTML tags:
<pre data-executable="true" data-language="python">
%matplotlib widget
</pre>
Examples¶
Using ipympl, you can display a variety of interactive plots.
Press the “Activate” button below to connect to a Jupyter server:
2D plot¶
%matplotlib widget import matplotlib.pyplot as plt fig, ax = plt.subplots() fig.canvas.layout.width = '7in' fig.canvas.layout.height= '5in' ax.plot([1,2,3], [4,5,3])
3D plot¶
%matplotlib widget from mpl_toolkits.mplot3d import axes3d fig = plt.figure() ax = fig.add_subplot(111, projection='3d') X, Y, Z = axes3d.get_test_data(0.05) ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) plt.show()
Plotly Example¶
Thebe can display output from plotly.py.
Setup¶
Be sure to load require.js before any of your thebe activation code so that the Jupyter widgets can function:
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
Configure thebe and load it:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "plotly/plotly.py",
ref: "doc-prod",
binderUrl: "https://mybinder.org",
repoProvider: "github",
},
}
</script>
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Create a button to activate thebe:
<button id="activateButton" style="width: 120px; height: 40px; font-size: 1.5em;">
Activate
</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Now add code cells between these HTML tags:
<pre data-executable="true" data-language="python"></pre>
Example¶
Press the “Activate” button below to connect to a Jupyter server:
Here is a distribution plot example from https://plotly.com/python/distplot/ (MIT License):
import plotly.express as px df = px.data.tips() fig = px.histogram(df, x="total_bill", y="tip", color="sex", marginal="rug", hover_data=df.columns) fig.show()
IPyCytoscape Example¶
Thebe can display output from ipycytoscape, which could visualize graphs using Cytoscape.js.
Setup¶
Be sure to load require.js before any of your thebe activation code so that the Cytoscape visualizations can function:
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
Configure thebe and load it:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "QuantStack/ipycytoscape",
ref: "1.2.0",
repoProvider: "github",
},
}
</script>
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Create a button to activate thebe:
<button id="activateButton" style="width: 120px; height: 40px; font-size: 1.5em;">
Activate
</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Now add code cells between these HTML tags:
<pre data-executable="true" data-language="python"></pre>
Example¶
Using Cytoscape, you can display a graph with several nodes. This example is from the ipycytoscape repository and is licensed under the BSD 3-Clause License.
.._example: https://github.com/QuantStack/ipycytoscape/blob/master/examples/Text%20on%20node.ipynb
Press the “Activate” button below to connect to a Jupyter server:
import ipycytoscape data = { 'nodes': [ { 'data': { 'id': 'desktop', 'name': 'Cytoscape', 'href': 'http://cytoscape.org' } }, { 'data': { 'id': 'a', 'name': 'Grid', 'href': 'http://cytoscape.org' } }, { 'data': { 'id': 'b', 'name': 'Cola', 'href': 'http://cytoscape.org' } }, { 'data': { 'id': 'c', 'name': 'Popper', 'href': 'http://cytoscape.org' } }, { 'data': { 'id': 'js', 'name': 'Cytoscape.js', 'href': 'http://js.cytoscape.org' } } ], 'edges': [ {'data': { 'source': 'desktop', 'target': 'js' }}, {'data': { 'source': 'a', 'target': 'b' }}, {'data': { 'source': 'a', 'target': 'c' }}, {'data': { 'source': 'b', 'target': 'c' }}, {'data': { 'source': 'js', 'target': 'b' }} ] } cytoscapeobj = ipycytoscape.CytoscapeWidget() cytoscapeobj.graph.add_graph_from_json(data) cytoscapeobj.set_style([{ 'selector': 'node', 'css': { 'content': 'data(name)', 'text-valign': 'center', 'color': 'white', 'text-outline-width': 2, 'text-outline-color': 'green', 'background-color': 'green' } }, { 'selector': ':selected', 'css': { 'background-color': 'black', 'line-color': 'black', 'target-arrow-color': 'black', 'source-arrow-color': 'black', 'text-outline-color': 'black' }} ]) cytoscapeobj
Pythreejs Example¶
Thebe can display output from pythreejs. The examples are taken from the pythreejs documentation and are licensed under the BSD 3-Clause License.
Setup¶
Be sure to load require.js before any of your thebe activation code so that the Jupyter widgets can function:
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
Configure thebe and load it:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "jupyter-widgets/pythreejs",
ref: "2.2.1",
binderUrl: "https://mybinder.org",
repoProvider: "github",
},
}
</script>
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Create a button to activate thebe:
<button id="activateButton" style="width: 120px; height: 40px; font-size: 1.5em;">
Activate
</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Now add code cells between these HTML tags:
<pre data-executable="true" data-language="python"></pre>
Examples¶
Press the “Activate” button below to connect to a Jupyter server:
Primitive shapes can be displayed:
from pythreejs import BoxGeometry BoxGeometry( width=5, height=10, depth=15, widthSegments=5, heightSegments=10, depthSegments=15)
More complex shapes can be constructed and viewed:
from IPython.display import display from pythreejs import (ParametricGeometry, Mesh, PerspectiveCamera, Scene, MeshLambertMaterial, DirectionalLight, AmbientLight, Renderer, OrbitControls, PerspectiveCamera) f = """ function f(origu, origv, out) { // scale u and v to the ranges I want: [0, 2*pi] var u = 2*Math.PI*origu; var v = 2*Math.PI*origv; var x = Math.sin(u); var y = Math.cos(v); var z = Math.cos(u+v); out.set(x,y,z); } """ surf_g = ParametricGeometry(func=f, slices=16, stacks=16) surf = Mesh(geometry=surf_g, material=MeshLambertMaterial(color='green', side='FrontSide')) surf2 = Mesh(geometry=surf_g, material=MeshLambertMaterial(color='yellow', side='BackSide')) c = PerspectiveCamera(position=[5, 5, 3], up=[0, 0, 1], children=[DirectionalLight(color='white', position=[3, 5, 1], intensity=0.6)]) scene = Scene(children=[surf, surf2, c, AmbientLight(intensity=0.5)]) renderer = Renderer(camera=c, scene=scene, controls=[OrbitControls(controlling=c)], width=400, height=400) display(renderer)
Matplotlib + Ipywidgets Interact Example¶
Thebe can display interactive plots using matplotlib and ipywidget’s interact.
Setup¶
Be sure to load require.min.js and Font Awesome 4 before any of your thebe activation code, it is required for the widget and its icons to work:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
Configure thebe and load it:
<script type="text/x-thebe-config">
{
requestKernel: true,
binderOptions: {
repo: "matplotlib/ipympl",
ref: "0.6.1",
repoProvider: "github",
},
}
</script>
<script src="https://unpkg.com/thebe@latest/lib/index.js"></script>
Create a button to activate thebe:
<button id="activateButton" style="width: 120px; height: 40px; font-size: 1.5em;">
Activate
</button>
<script>
var bootstrapThebe = function() {
thebelab.bootstrap();
}
document.querySelector("#activateButton").addEventListener('click', bootstrapThebe)
</script>
Now add code cells between these HTML tags:
<pre data-executable="true" data-language="python"></pre>
Example¶
Press the “Activate” button below to connect to a Jupyter server:
Here is a simple interactive sine plot example:
%matplotlib widget import ipywidgets as widgets import matplotlib.pyplot as plt import numpy as np x = np.linspace(0,10) def sine_func(x, w, amp): return amp*np.sin(w*x) @widgets.interact(w=(0, 4, 0.25), amp=(0, 4, .1)) def update(w = 1, amp = 1): plt.clf() plt.ylim(-4, 4) plt.plot(x, sine_func(x, w, amp))
Alternative computational environments; code cells with prompts and outputs
Thebe in use for SageMath documentation (about) Showcases a fancy activate button, and fetching thebe and running computations locally when possible. Relevant files:
Acknowledgements¶
thebe
was originally developed as a part of OpenDreamKit -
Horizon 2020 European Research Infrastructure project (676541).