update,
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
.ipynb_checkpoints
|
||||
.ipynb_checkpoints/.
|
||||
.ipynb_checkpoints/
|
||||
|
||||
.ropeproject
|
||||
__pycache__
|
@@ -0,0 +1,6 @@
|
||||
# Notes for Making Changes
|
||||
|
||||
1. The notebooks need to contain execution output for NBViewer
|
||||
1. The notebooks should be run in an env created with `conda env create -n bokeh-notebooks -f environment.yml`. Make sure to activate your env with `conda activate bokeh-notebooks` before using or developing the notebooks!
|
||||
1. Oneliner to run the notebooks `git ls-files -z \*.ipynb | xargs -0 jupyter nbconvert --to notebook --inplace --execute`
|
||||
1. While working on changes, if you want to strip the output from the notebooks you can `git ls-files -z \*.ipynb | xargs -0 jupyter nbconvert --clear-output`
|
@@ -0,0 +1,28 @@
|
||||
Copyright (c) 2012, Continuum Analytics, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of Continuum Analytics nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,22 @@
|
||||
Bokeh in Jupyter Notebooks
|
||||
==========================
|
||||
|
||||
Welcome to [Bokeh](https://bokeh.org/) in Jupyter Notebooks!
|
||||
|
||||
Bokeh is a Python interactive visualization library for large datasets that
|
||||
natively uses the latest web technologies. Its goal is to provide elegant,
|
||||
concise construction of novel graphics in the style of Protovis/D3, while
|
||||
delivering high-performance interactivity over large data to thin clients.
|
||||
|
||||
These Jupyter notebooks provide useful Bokeh examples and a tutorial to get
|
||||
started. You can download the repository and execute `jupyter notebook` from
|
||||
your terminal to try out the notebooks locally on your own machine.
|
||||
|
||||
Alternatively, you can immediately launch live versions of the Tutorial
|
||||
notebooks in your browser on [mybinder.org](https://mybinder.org/v2/gh/bokeh/bokeh-notebooks/master?filepath=tutorial%2F00%20-%20Introduction%20and%20Setup.ipynb).
|
||||
|
||||
Please visit the [Bokeh web page](https://bokeh.org) for
|
||||
more information and full documentation, and the [Bokeh Discourse](https://discourse.bokeh.org/)
|
||||
for community discussion.
|
||||
|
||||
Be sure to follow us on Twitter [@bokeh](https://twitter.com/bokeh)!
|
@@ -0,0 +1,22 @@
|
||||
name: bokeh
|
||||
|
||||
channels:
|
||||
- bokeh
|
||||
- conda-forge
|
||||
|
||||
dependencies:
|
||||
- python=3.10
|
||||
- numpy
|
||||
- notebook
|
||||
- bokeh>=3.0
|
||||
- pandas
|
||||
- scipy
|
||||
- selenium
|
||||
- datashader
|
||||
- networkx
|
||||
- flask
|
||||
- firefox
|
||||
- geckodriver
|
||||
- holoviews
|
||||
- hvplot
|
||||
- jupyter_contrib_nbextensions
|
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/images/bokeh-transparent.png
(Stored with Git LFS)
Normal file
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/images/bokeh-transparent.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div>\n",
|
||||
"<a href=\"https://bokeh.org/\"><img src=\"https://bokeh.org/img/hero.png\"></a>\n",
|
||||
"</div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Welcome to [Bokeh](https://bokeh.org) in the Jupyter Notebook!\n",
|
||||
"\n",
|
||||
"Bokeh is a Python interactive visualization library that targets modern web browsers for presentation. Its goal is to provide elegant, concise construction of novel graphics in the style of D3.js, and to extend this capability with high-performance interactivity over very large or streaming datasets. Bokeh can help anyone who would like to quickly and easily create interactive plots, dashboards, and data applications."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Quickstart\n",
|
||||
"\n",
|
||||
"Get started with a [5-min introduction to Bokeh](quickstart/quickstart.ipynb)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Tutorial\n",
|
||||
"\n",
|
||||
"Start with the [Introduction and Setup](tutorial/00%20-%20Introduction%20and%20Setup.ipynb) notebook and jump to any of the specific topic sections from there."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## More information\n",
|
||||
"\n",
|
||||
"Find more details and contact information at https://bokeh.org.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Thanks\n",
|
||||
"\n",
|
||||
"Bokeh was originally developed with financial support from [Anaconda, Inc.](https://anaconda.com) and the Darpa XDATA initiative, and continues due to support from NumFOCUS and individual community contributions. Many thanks to [all of the Bokeh Github contributors](https://github.com/bokeh/bokeh/graphs/contributors)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<script>\n",
|
||||
" (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n",
|
||||
" (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n",
|
||||
" m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n",
|
||||
" })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n",
|
||||
"\n",
|
||||
" ga('create', 'UA-27761864-9', 'auto');\n",
|
||||
" ga('send', 'pageview');\n",
|
||||
"</script>"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.8"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@@ -0,0 +1 @@
|
||||
python -c "exec(\"import bokeh\\nbokeh.sampledata.download()\")"
|
@@ -0,0 +1 @@
|
||||
barplot.html
|
@@ -0,0 +1,359 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div>\n",
|
||||
"<a href=\"https://bokeh.org/\"><img src=\"https://bokeh.org/img/hero.png\"></a>\n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
"<table style=\"float:left; border:none\">\n",
|
||||
" <tr style=\"border:none\">\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <a href=\"https://bokeh.org/\"> \n",
|
||||
" <img \n",
|
||||
" src=\"../tutorial/assets/bokeh-transparent.png\" \n",
|
||||
" style=\"width:50px\"\n",
|
||||
" >\n",
|
||||
" </a> \n",
|
||||
" </td>\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <h1>Bokeh Quickstart</h1>\n",
|
||||
" </td>\n",
|
||||
" </tr>\n",
|
||||
"</table>\n",
|
||||
"\n",
|
||||
"<div style=\"float:right;\"><h2>Bokeh 5-minute Overview</h2></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Bokeh is a Python interactive visualization library that targets modern web browsers for presentation. Its goal is to provide elegant, concise construction of novel graphics in the style of D3.js, and to extend this capability with high-performance interactivity over very large or streaming datasets. Bokeh can help anyone who would like to quickly and easily create interactive plots, dashboards, and data applications.\n",
|
||||
"\n",
|
||||
"## Simple Example\n",
|
||||
"Here is a simple first example. First we'll import the figure function from bokeh.plotting, which will let us create all sorts of interesting plots easily. We also import the show and ouptut_notebook functions from bokeh.io — these let us display our results inline in the notebook."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.plotting import figure \n",
|
||||
"from bokeh.io import output_notebook, show"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Next, we'll tell Bokeh to display its plots directly into the notebook. This will cause all of the Javascript and data to be embedded directly into the HTML of the notebook itself. (Bokeh can output straight to HTML files, or use a server, which we'll look at later.)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"output_notebook()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Next, we'll import NumPy and create some simple data."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from numpy import cos, linspace\n",
|
||||
"x = linspace(-6, 6, 100)\n",
|
||||
"y = cos(x)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now we'll call Bokeh's figure function to create a plot p. Then we call the `circle()` method of the plot to render a red circle at each of the points in *x* and *y*.\n",
|
||||
"\n",
|
||||
"We can immediately interact with the plot:\n",
|
||||
"\n",
|
||||
"- click-drag will pan the plot around.\n",
|
||||
"- mousewheel will zoom in and out (after enabling in the toolbar)\n",
|
||||
"\n",
|
||||
"The toolbar below is the default one that is available for all plots. It can be configured further via the tools keyword argument."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"p = figure(width=500, height=500)\n",
|
||||
"p.circle(x, y, size=7, color=\"firebrick\", alpha=0.5)\n",
|
||||
"show(p)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bar Plot Example\n",
|
||||
"Bokeh's core display model relies on *composing graphical primitives* which are bound to data series. This is similar in spirit to D3, and different than most other Python plotting libraries.\n",
|
||||
"\n",
|
||||
"A slightly more sophisticated example demonstrates this idea.\n",
|
||||
"\n",
|
||||
"Bokeh ships with a small set of interesting \"sample data\" in the `bokeh.sampledata` package. We'll load up some historical automobile mileage data, which is returned as a Pandas `DataFrame`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.sampledata.autompg import autompg\n",
|
||||
"\n",
|
||||
"grouped = autompg.groupby(\"yr\")\n",
|
||||
"\n",
|
||||
"mpg = grouped.mpg\n",
|
||||
"avg, std = mpg.mean(), mpg.std()\n",
|
||||
"years = list(grouped.groups)\n",
|
||||
"american = autompg[autompg[\"origin\"]==1]\n",
|
||||
"japanese = autompg[autompg[\"origin\"]==3]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"For each year, we want to plot the distribution of MPG within that year."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"p = figure(title=\"MPG by Year (Japan and US)\")\n",
|
||||
"\n",
|
||||
"p.vbar(x=years, bottom=avg-std, top=avg+std, width=0.8, \n",
|
||||
" fill_alpha=0.2, line_color=None, legend_label=\"MPG 1 stddev\")\n",
|
||||
"\n",
|
||||
"p.circle(x=japanese[\"yr\"], y=japanese[\"mpg\"], size=10, alpha=0.5,\n",
|
||||
" color=\"red\", legend_label=\"Japanese\")\n",
|
||||
"\n",
|
||||
"p.triangle(x=american[\"yr\"], y=american[\"mpg\"], size=10, alpha=0.3,\n",
|
||||
" color=\"blue\", legend_label=\"American\")\n",
|
||||
"\n",
|
||||
"p.legend.location = \"top_left\"\n",
|
||||
"show(p)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**This kind of approach can be used to generate other kinds of interesting plots**. See many more examples in the [Bokeh Documentation Gallery](https://docs.bokeh.org/en/latest/docs/gallery.html).\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Linked Brushing\n",
|
||||
"To link plots together at a data level, we can explicitly wrap the data in a `ColumnDataSource`. This allows us to reference columns by name.\n",
|
||||
"\n",
|
||||
"We can use a \"select\" tool to select points on one plot, and the linked points on the other plots will highlight."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.models import ColumnDataSource\n",
|
||||
"from bokeh.layouts import gridplot\n",
|
||||
"\n",
|
||||
"source = ColumnDataSource(autompg)\n",
|
||||
"\n",
|
||||
"options = dict(width=300, height=300,\n",
|
||||
" tools=\"pan,wheel_zoom,box_zoom,box_select,lasso_select\")\n",
|
||||
"\n",
|
||||
"p1 = figure(title=\"MPG by Year\", **options)\n",
|
||||
"p1.circle(\"yr\", \"mpg\", color=\"blue\", source=source)\n",
|
||||
"\n",
|
||||
"p2 = figure(title=\"HP vs. Displacement\", **options)\n",
|
||||
"p2.circle(\"hp\", \"displ\", color=\"green\", source=source)\n",
|
||||
"\n",
|
||||
"p3 = figure(title=\"MPG vs. Displacement\", **options)\n",
|
||||
"p3.circle(\"mpg\", \"displ\", size=\"cyl\", line_color=\"red\", fill_color=None, source=source)\n",
|
||||
"\n",
|
||||
"p = gridplot([[ p1, p2, p3]], toolbar_location=\"right\")\n",
|
||||
"\n",
|
||||
"show(p)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"You can read more about the `ColumnDataSource` and other Bokeh data structures in [Providing Data for Plots and Tables](https://docs.bokeh.org/en/latest/docs/user_guide/data.html)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Standalone HTML\n",
|
||||
"In addition to working well with the Notebook, Bokeh can also save plots out into their own HTML files. Here is the bar plot example from above, but saving into its own standalone file.\n",
|
||||
"\n",
|
||||
"Now when we call `show()`, a new browser tab is also opened with the plot. If we just wanted to save the file, we would use `save()` instead."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.plotting import output_file\n",
|
||||
"\n",
|
||||
"output_file(\"barplot.html\")\n",
|
||||
"\n",
|
||||
"p = figure(title=\"MPG by Year (Japan and US)\")\n",
|
||||
"\n",
|
||||
"p.vbar(x=years, bottom=avg-std, top=avg+std, width=0.8, \n",
|
||||
" fill_alpha=0.2, line_color=None, legend_label=\"MPG 1 stddev\")\n",
|
||||
"\n",
|
||||
"p.circle(x=japanese[\"yr\"], y=japanese[\"mpg\"], size=10, alpha=0.3,\n",
|
||||
" color=\"red\", legend_label=\"Japanese\")\n",
|
||||
"\n",
|
||||
"p.triangle(x=american[\"yr\"], y=american[\"mpg\"], size=10, alpha=0.3,\n",
|
||||
" color=\"blue\", legend_label=\"American\")\n",
|
||||
"\n",
|
||||
"p.legend.location = \"top_left\"\n",
|
||||
"show(p)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bokeh Applications\n",
|
||||
"Bokeh also has a server component that can be used to build interactive web applications that easily connect the powerful constellation of PyData tools to sophisticated Bokeh visualizations. The Bokeh server can be used to:\n",
|
||||
"\n",
|
||||
"- respond to UI and tool events generated in a browser with computations or queries using the full power of python\n",
|
||||
"- automatically push server-side updates to the UI (i.e. widgets or plots in a browser)\n",
|
||||
"- use periodic, timeout, and asynchronous callbacks to drive streaming updates\n",
|
||||
"\n",
|
||||
"The cell below shows a simple deployed Bokeh application from https://demo.bokeh.org embedded in an IFrame. Scrub the sliders or change the title to see the plot update."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from IPython.display import IFrame\n",
|
||||
"IFrame('https://demo.bokeh.org/sliders', width=900, height=410)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<p>Click on any of the thumbnails below to launch other live Bokeh applications.</p>\n",
|
||||
"<center>\n",
|
||||
"<a href=\"https://demo.bokeh.org/crossfilter\">\n",
|
||||
" <img \n",
|
||||
" width=\"30%\" height=\"30%\" style=\"display: inline ; padding: 10px;\" \n",
|
||||
" src=\"https://bokeh.pydata.org/static/crossfilter_t.png\"\n",
|
||||
" >\n",
|
||||
"</a>\n",
|
||||
"\n",
|
||||
"<a href=\"https://demo.bokeh.org/movies\">\n",
|
||||
" <img \n",
|
||||
" width=\"30%\" height=\"30%\" style=\"display: inline ; padding: 10px;\" \n",
|
||||
" src=\"https://bokeh.pydata.org/static/movies_t.png\" \n",
|
||||
" >\n",
|
||||
"</a>\n",
|
||||
"\n",
|
||||
"<a href=\"https://demo.bokeh.org/gapminder\">\n",
|
||||
" <img \n",
|
||||
" width=\"30%\" height=\"30%\" style=\"display: inline ; padding: 10px;\" \n",
|
||||
" src=\"https://bokeh.pydata.org/static/gapminder_t.png\"\n",
|
||||
" >\n",
|
||||
"</a>\n",
|
||||
"</center><p>Find more details and information about developing and deploying Bokeh server applications in the User's Guide chapter <a href=\"https://docs.bokeh.org/en/latest/docs/user_guide/server.html\">Running a Bokeh Server</a>.</p>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<h2 id=\"BokehJS\">BokehJS<a class=\"anchor-link\" href=\"#BokehJS\">¶</a></h2><p>At its core, Bokeh consists of a Javascript library, <a href=\"https://github.com/bokeh/bokeh/tree/branch-3.0/bokehjs\">BokehJS</a>, and a Python binding which provides classes and objects that ultimately generate a JSON representation of the plot structure.</p>\n",
|
||||
"<p>You can read more about design and usage in the <a href=\"https://docs.bokeh.org/en/latest/docs/user_guide/advanced/bokehjs.html\">BokehJS</a> section of the Bokeh User's Guide.</p>\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<h2 id=\"More-Information\">More Information<a class=\"anchor-link\" href=\"#More-Information\">¶</a></h2><p>Find more details and information at <a href=\"https://bokeh.org\">https://bokeh.org</a>.</p>\n",
|
||||
"<p><img src=\"http://static.bokeh.org/logos/logotype.svg\" width=\"256px\" height=\"64px\"></p>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.8"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
plot.html
|
||||
plot.png
|
||||
plot.svg
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,393 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table style=\"float:left; border:none\">\n",
|
||||
" <tr style=\"border:none\">\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <a href=\"https://bokeh.org/\"> \n",
|
||||
" <img \n",
|
||||
" src=\"assets/bokeh-transparent.png\" \n",
|
||||
" style=\"width:50px\"\n",
|
||||
" >\n",
|
||||
" </a> \n",
|
||||
" </td>\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <h1>Bokeh Tutorial</h1>\n",
|
||||
" </td>\n",
|
||||
" </tr>\n",
|
||||
"</table>\n",
|
||||
"\n",
|
||||
"<div style=\"float:right;\"><h2>11. Running Bokeh Applications</h2></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The architecture of Bokeh is such that high-level “model objects” (representing things like plots, ranges, axes, glyphs, etc.) are created in Python, and then converted to a JSON format that is consumed by the client library, BokehJS. Using the Bokeh Server, it is possible to keep the “model objects” in python and in the browser in sync with one another, creating powerful capabilities:\n",
|
||||
"\n",
|
||||
"* respond to UI and tool events generated in a browser with computations or queries using the full power of python\n",
|
||||
"* automatically push updates the UI (i.e. widgets or plots), in a browser\n",
|
||||
"* use periodic, timeout, and asychronous callbacks drive streaming updates\n",
|
||||
"\n",
|
||||
"***This capability to synchronize between python and the browser is the main purpose of the Bokeh Server.***"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.io import output_notebook, show\n",
|
||||
"output_notebook()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bokeh Apps in Notebooks\n",
|
||||
"\n",
|
||||
"The easiest way to embed a Bokeh application in a notebook is to make a function `modify_doc(doc)` that creates Bokeh content, and adds it to the document. This function can be passed to `show`, and the app defined by the function will be displayed inline. A short complete example is below"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.layouts import column\n",
|
||||
"from bokeh.models import TextInput, Button, Paragraph\n",
|
||||
"\n",
|
||||
"def modify_doc(doc):\n",
|
||||
" \n",
|
||||
" # create some widgets\n",
|
||||
" button = Button(label=\"Say HI\")\n",
|
||||
" input = TextInput(value=\"Bokeh\")\n",
|
||||
" output = Paragraph()\n",
|
||||
"\n",
|
||||
" # add a callback to a widget\n",
|
||||
" def update():\n",
|
||||
" output.text = \"Hello, \" + input.value\n",
|
||||
" button.on_click(update)\n",
|
||||
"\n",
|
||||
" # create a layout for everything\n",
|
||||
" layout = column(button, input, output)\n",
|
||||
"\n",
|
||||
" # add the layout to curdoc\n",
|
||||
" doc.add_root(layout)\n",
|
||||
" \n",
|
||||
"# In the notebook, just pass the function that defines the app to show\n",
|
||||
"# You may need to supply notebook_url, e.g notebook_url=\"http://localhost:8889\" \n",
|
||||
"show(modify_doc) "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# EXERCISE: add a Select widget to this example that offers several different greetings\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bokeh Apps with `bokeh serve`\n",
|
||||
"\n",
|
||||
"It's also possible to define Bokeh applications by creating a standard Python script. In this case, there is no need to make a function like `modify_doc`. Typically, the script should simply create all the Bokeh content, then add it to the doc with a line like\n",
|
||||
"```python\n",
|
||||
"curdoc().add_root(layout)\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"To try out the example below, copy the code into a file ``hello.py`` and then execute:\n",
|
||||
"```bash\n",
|
||||
"bokeh serve --show hello.py \n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"<center><div style=\"font-size: 14pt;color: firebrick;\"> NOTE: The exercise below require work outside the notebook <div></center>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"```python\n",
|
||||
"# hello.py \n",
|
||||
"\n",
|
||||
"from bokeh.io import curdoc\n",
|
||||
"from bokeh.layouts import column\n",
|
||||
"from bokeh.models.widgets import TextInput, Button, Paragraph\n",
|
||||
"\n",
|
||||
"# create some widgets\n",
|
||||
"button = Button(label=\"Say HI\")\n",
|
||||
"input = TextInput(value=\"Bokeh\")\n",
|
||||
"output = Paragraph()\n",
|
||||
"\n",
|
||||
"# add a callback to a widget\n",
|
||||
"def update():\n",
|
||||
" output.text = \"Hello, \" + input.value\n",
|
||||
"button.on_click(update)\n",
|
||||
"\n",
|
||||
"# create a layout for everything\n",
|
||||
"layout = column(button, input, output)\n",
|
||||
"\n",
|
||||
"# add the layout to curdoc\n",
|
||||
"curdoc().add_root(layout)\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Copy this code to a script `hello.py` and run it with the Bokeh server."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Linking Plots and Widgets\n",
|
||||
"\n",
|
||||
"Lets take a look at a more involved example that links several widgets to a plot. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from numpy.random import random\n",
|
||||
"\n",
|
||||
"from bokeh.layouts import column, row\n",
|
||||
"from bokeh.plotting import figure\n",
|
||||
"from bokeh.models import ColumnDataSource, Select, TextInput\n",
|
||||
"\n",
|
||||
"def get_data(N):\n",
|
||||
" return dict(x=random(size=N), y=random(size=N), r=random(size=N) * 0.03)\n",
|
||||
"\n",
|
||||
"COLORS = [\"black\", \"firebrick\", \"navy\", \"olive\", \"goldenrod\"]\n",
|
||||
"\n",
|
||||
"def modify_doc(doc):\n",
|
||||
" source = ColumnDataSource(data=get_data(200))\n",
|
||||
"\n",
|
||||
" p = figure(tools=\"\", toolbar_location=None)\n",
|
||||
" r = p.circle(x='x', y='y', radius='r', source=source,\n",
|
||||
" color=\"navy\", alpha=0.6, line_color=\"white\")\n",
|
||||
"\n",
|
||||
" \n",
|
||||
" select = Select(title=\"Color\", value=\"navy\", options=COLORS)\n",
|
||||
" input = TextInput(title=\"Number of points\", value=\"200\")\n",
|
||||
"\n",
|
||||
" def update_color(attrname, old, new):\n",
|
||||
" r.glyph.fill_color = select.value\n",
|
||||
" select.on_change('value', update_color)\n",
|
||||
"\n",
|
||||
" def update_points(attrname, old, new):\n",
|
||||
" N = int(input.value)\n",
|
||||
" source.data = get_data(N)\n",
|
||||
" input.on_change('value', update_points)\n",
|
||||
"\n",
|
||||
" layout = column(row(select, input, width=400), row(p))\n",
|
||||
"\n",
|
||||
" doc.add_root(layout)\n",
|
||||
"\n",
|
||||
"show(modify_doc)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# EXERCISE: add more widgets to change more aspects of this plot\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Streaming Data\n",
|
||||
"\n",
|
||||
"It is possible to efficiently stream new data to column data sources by using the ``stream`` method. This method accepts two argmuments:\n",
|
||||
"* ``new_data`` — a dictionary with the same structure as the column data source\n",
|
||||
"* ``rollover`` — a maximum column length on the client (earlier data is dropped) *[optional]*\n",
|
||||
"\n",
|
||||
"If no ``rollover`` is specified, data is never dropped on the client and columns grow without bound.\n",
|
||||
"\n",
|
||||
"It is often useful to use periodic callbacks in conjuction with streaming data The ``add_periodic_callback`` method of ``curdoc()`` accepts a callback function, and a time interval (in ms) to repeatedly execute the callback. \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from math import cos, sin\n",
|
||||
"\n",
|
||||
"from bokeh.models import ColumnDataSource\n",
|
||||
"\n",
|
||||
"def modify_doc(doc):\n",
|
||||
" p = figure(match_aspect=True)\n",
|
||||
" p.circle(x=0, y=0, radius=1, fill_color=None, line_width=2)\n",
|
||||
" \n",
|
||||
" # this is just to help the auto-datarange\n",
|
||||
" p.rect(0, 0, 2, 2, alpha=0)\n",
|
||||
"\n",
|
||||
" # this is the data source we will stream to\n",
|
||||
" source = ColumnDataSource(data=dict(x=[1], y=[0]))\n",
|
||||
" p.circle(x='x', y='y', size=12, fill_color='white', source=source)\n",
|
||||
"\n",
|
||||
" def update():\n",
|
||||
" x, y = source.data['x'][-1], source.data['y'][-1]\n",
|
||||
"\n",
|
||||
" # construct the new values for all columns, and pass to stream\n",
|
||||
" new_data = dict(x=[x*cos(0.1) - y*sin(0.1)], y=[x*sin(0.1) + y*cos(0.1)])\n",
|
||||
" source.stream(new_data, rollover=8)\n",
|
||||
"\n",
|
||||
" doc.add_periodic_callback(update, 150)\n",
|
||||
" doc.add_root(p)\n",
|
||||
" \n",
|
||||
"show(modify_doc)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"### EXERCISE: starting with the above example, create your own streaming plot\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Bokeh column data sources also support a `patch` method that can be used to efficiently update subsets of data."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Directory Format Apps and Templates\n",
|
||||
"\n",
|
||||
"Bokeh apps can also be defined with a directory format. This format affords the use of extra modules, data files, templates, theme files, and other features. The directory should contain a `main.py` which is the \"entry point\" for the app, but may contain extra parts:\n",
|
||||
"```\n",
|
||||
"myapp\n",
|
||||
" |\n",
|
||||
" +---main.py\n",
|
||||
" +---server_lifecycle.py\n",
|
||||
" +---static\n",
|
||||
" +---theme.yaml\n",
|
||||
" +---templates\n",
|
||||
" +---index.html\n",
|
||||
"```\n",
|
||||
"The [Directory Format](https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#directory-format) section of the User's Guide has more information. \n",
|
||||
"\n",
|
||||
"See a complete sophisticated example at: https://github.com/bokeh/bokeh/tree/master/examples/app/dash\n",
|
||||
"\n",
|
||||
"<img src=\"https://static.bokeh.org/dash.png\">"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Tips and Tricks\n",
|
||||
"\n",
|
||||
" \n",
|
||||
"* Real Python callbacks *require* a Bokeh server application. They cannot work with `output_file`, `components` or other functions that generate standalone output. Standalone content can only use `CustomJS` callbacks. \n",
|
||||
"\n",
|
||||
"\n",
|
||||
"* Try to update data sources \"all at once\" whenever possible, i.e. prefer this:\n",
|
||||
" ```python\n",
|
||||
" source.data = new_data_dict # GOOD\n",
|
||||
" ```\n",
|
||||
" rather then updating individual columns sequentially:\n",
|
||||
" ```python\n",
|
||||
" # LESS GOOD\n",
|
||||
" source.data['foo'] = new_foo_column\n",
|
||||
" source.data['bar'] = new_bar_column \n",
|
||||
" ```\n",
|
||||
" If the new columns are exactly the same length as the old ones, then updating sequentially will trigger extra updates and may result in bad visual effects. \n",
|
||||
" If the new columns are a different length than the old ones, then updating \"all at once\" is **mandatory**.\n",
|
||||
" \n",
|
||||
"\n",
|
||||
"* Each time a session is started, the Bokeh server runs the script (or `modify_doc`) function, and the code that is run ***must return completely new Bokeh objects every time***. It is not possible to share Bokeh objects between sessions. As a concrete example, this is what NOT to do:\n",
|
||||
" ```python\n",
|
||||
" source = ColumnDataSource(data) # VERY BAD - global outside modify_doc\n",
|
||||
" \n",
|
||||
" def modify_doc(doc):\n",
|
||||
" p = figure()\n",
|
||||
" p.circle('x', 'y', source=source)\n",
|
||||
" doc.add_root(p)\n",
|
||||
" \n",
|
||||
" ```\n",
|
||||
" The analogous situation would occur with a script if the script imports a global Bokeh object from a separate module (due to the way Python caches imports)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Next Section"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This is the last section of the main tutorial. To explore some extra topics, see the appendices:\n",
|
||||
"\n",
|
||||
"[A1 - Models and Primitives](A1%20-%20Models%20and%20Primitives.ipynb)<br />\n",
|
||||
"[A2 - Visualizing Big Data with Datashader](A2%20-%20Visualizing%20Big%20Data%20with%20Datashader.ipynb)<br />\n",
|
||||
"[A3 - High-Level Charting with Holoviews](A3%20-%20High-Level%20Charting%20with%20Holoviews.ipynb)<br />\n",
|
||||
"[A4 - Additional Resources](A4%20-%20Additional%20Resources.ipynb)\n",
|
||||
"\n",
|
||||
"To go back to the overview, click [here](00%20-%20Introduction%20and%20Setup.ipynb)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.13"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@@ -0,0 +1,620 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table style=\"float:left; border:none\">\n",
|
||||
" <tr style=\"border:none\">\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <a href=\"https://bokeh.org/\"> \n",
|
||||
" <img \n",
|
||||
" src=\"assets/bokeh-transparent.png\" \n",
|
||||
" style=\"width:50px\"\n",
|
||||
" >\n",
|
||||
" </a> \n",
|
||||
" </td>\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <h1>Bokeh Tutorial</h1>\n",
|
||||
" </td>\n",
|
||||
" </tr>\n",
|
||||
"</table>\n",
|
||||
"\n",
|
||||
"<div style=\"float:right;\"><h2>A1. Models and Primitives</h2></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Overview\n",
|
||||
"\n",
|
||||
"Although typically referred to by a single name, Bokeh comprises two separate libraries. \n",
|
||||
"\n",
|
||||
"The first component is a JavaScript library, BokehJS, that runs in the browser. This library is responsible for all of the rendering and user interaction. Its input is a collection of declarative JSON objects that comprise a “scenegraph”. The objects in this scenegraph describe everything that BokehJS should handle: what plots and widgets are present and in what arrangement, what tools and renderers and axes the plots will have, etc. These JSON objects are converted into JavaScript objects in the browser.\n",
|
||||
"\n",
|
||||
"The second component is a library in Python (or other languages) that can generate the JSON described above. In the Python Bokeh library, this is accomplished at the lowest level by exposing a set of `Model` subclasses that exactly mirror the set of BokehJS Models that are use in the browser. Most of the models are very simple, usually consisting of a few property attributes and no methods. Model attributes can either be configured when the model is created, or later by setting attribute values on the model object:\n",
|
||||
"\n",
|
||||
"#### properties can be configured when a model object is initialized\n",
|
||||
"```python\n",
|
||||
"glyph = Rect(x=\"x\", y=\"y2\", w=10, h=20, line_color=None)\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"#### properties can be configured by assigning values to attributes on exitsting models\n",
|
||||
"```python\n",
|
||||
"glyph.fill_alpha = 0.5\n",
|
||||
"glyph.fill_color = \"navy\"\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"These methods of configuration work in general for all Bokeh models. \n",
|
||||
"\n",
|
||||
"Bokeh models are eventually collected into a Bokeh `Document` for serialization between BokehJS and the Bokeh Python bindings. As an example, the following image shows an example document for simple plot:\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Such a document could be created at a high level using the `bokeh.plotting` API, which automatically assembles any models such as axes and grids and toolbars in a reasonable way. However it is also possible to assemble all the components \"by hand\" using the low-level `bokeh.models` API. Using the `bokeh.models` interface provides complete control over how Bokeh plots and Bokeh widgets are put together and configured. However, it provides no help with assembling the models in meaningful or correct ways. It is entirely up to developers to build the scenegraph “by hand”. \n",
|
||||
"\n",
|
||||
"For more information about the details of all Bokeh models, consult the [Reference Guide](https://bokeh.pydata.org/en/latest/docs/reference.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Example Walkthrough\n",
|
||||
"\n",
|
||||
"Let's try to reproduce this NYTimes interactive chart [Usain Bolt vs. 116 years of Olympic sprinters](http://www.nytimes.com/interactive/2012/08/05/sports/olympics/the-100-meter-dash-one-race-every-medalist-ever.html) using the `bokeh.models` interface."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The first thing we need is to get the data. The data for this chart is located in the ``bokeh.sampledata`` module as a Pandas DataFrame. You can see the first ten rows below:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.sampledata.sprint import sprint\n",
|
||||
"sprint[:10]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Next we import some of the Bokeh models that need to be assembled to make a plot. At a minimum, we need to start with ``Plot``, the glyphs (``Circle`` and ``Text``) we want to display, as well as ``ColumnDataSource`` to hold the data and range objects to set the plot bounds. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.io import output_notebook, show\n",
|
||||
"from bokeh.models import Circle, Text, ColumnDataSource, Range1d, DataRange1d, Plot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"output_notebook()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Setting up Data\n",
|
||||
"\n",
|
||||
"Next we need set up all the columns we want in our column data source. Here we add a few extra columns like `MetersBack` and `SelectedName` that we will use for a `HoverTool` later."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"abbrev_to_country = {\n",
|
||||
" \"USA\": \"United States\",\n",
|
||||
" \"GBR\": \"Britain\",\n",
|
||||
" \"JAM\": \"Jamaica\",\n",
|
||||
" \"CAN\": \"Canada\",\n",
|
||||
" \"TRI\": \"Trinidad and Tobago\",\n",
|
||||
" \"AUS\": \"Australia\",\n",
|
||||
" \"GER\": \"Germany\",\n",
|
||||
" \"CUB\": \"Cuba\",\n",
|
||||
" \"NAM\": \"Namibia\",\n",
|
||||
" \"URS\": \"Soviet Union\",\n",
|
||||
" \"BAR\": \"Barbados\",\n",
|
||||
" \"BUL\": \"Bulgaria\",\n",
|
||||
" \"HUN\": \"Hungary\",\n",
|
||||
" \"NED\": \"Netherlands\",\n",
|
||||
" \"NZL\": \"New Zealand\",\n",
|
||||
" \"PAN\": \"Panama\",\n",
|
||||
" \"POR\": \"Portugal\",\n",
|
||||
" \"RSA\": \"South Africa\",\n",
|
||||
" \"EUA\": \"United Team of Germany\",\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"fill_color = { \"gold\": \"#efcf6d\", \"silver\": \"#cccccc\", \"bronze\": \"#c59e8a\" }\n",
|
||||
"line_color = { \"gold\": \"#c8a850\", \"silver\": \"#b0b0b1\", \"bronze\": \"#98715d\" }\n",
|
||||
"\n",
|
||||
"def selected_name(name, medal, year):\n",
|
||||
" return name if medal == \"gold\" and year in [1988, 1968, 1936, 1896] else \"\"\n",
|
||||
"\n",
|
||||
"t0 = sprint.Time[0]\n",
|
||||
"\n",
|
||||
"sprint[\"Abbrev\"] = sprint.Country\n",
|
||||
"sprint[\"Country\"] = sprint.Abbrev.map(lambda abbr: abbrev_to_country[abbr])\n",
|
||||
"sprint[\"Medal\"] = sprint.Medal.map(lambda medal: medal.lower())\n",
|
||||
"sprint[\"Speed\"] = 100.0/sprint.Time\n",
|
||||
"sprint[\"MetersBack\"] = 100.0*(1.0 - t0/sprint.Time)\n",
|
||||
"sprint[\"MedalFill\"] = sprint.Medal.map(lambda medal: fill_color[medal])\n",
|
||||
"sprint[\"MedalLine\"] = sprint.Medal.map(lambda medal: line_color[medal])\n",
|
||||
"sprint[\"SelectedName\"] = sprint[[\"Name\", \"Medal\", \"Year\"]].apply(tuple, axis=1).map(lambda args: selected_name(*args))\n",
|
||||
"\n",
|
||||
"source = ColumnDataSource(sprint)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Building in stages\n",
|
||||
"\n",
|
||||
"Let's build up our plot in stages, stopping to check the output along the way to see how things look.\n",
|
||||
"\n",
|
||||
"As we go through, note the three methods that `Plot`, `Chart`, and `Figure` all have:\n",
|
||||
"\n",
|
||||
"* `p.add_glyph`\n",
|
||||
"* `p.add_tools`\n",
|
||||
"* `p.add_layout`\n",
|
||||
"\n",
|
||||
"These are actually small convenience methods that help us add models to `Plot` objects in the correct way."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Basic Plot with Just Glyphs\n",
|
||||
"\n",
|
||||
"First we create just the `Plot` with a title and some basic styling applied, as well add a few `Circle` glyphs for the actual race data. To manually configure glyphs, we first create a glyph object (e.g., `Text` or `Circle`) that is configured with the visual properties we want as well as the data columns to use for coordinates, etc. Then we call `plot.add_glyph` with the glyph, and the data source that the glyph should use. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"plot_options = dict(width=800, height=480, toolbar_location=None, outline_line_color=None)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"medal_glyph = Circle(x=\"MetersBack\", y=\"Year\", size=10, fill_color=\"MedalFill\", \n",
|
||||
" line_color=\"MedalLine\", fill_alpha=0.5)\n",
|
||||
"\n",
|
||||
"athlete_glyph = Text(x=\"MetersBack\", y=\"Year\", x_offset=10, text=\"SelectedName\",\n",
|
||||
" text_align=\"left\", text_baseline=\"middle\", text_font_size=\"9pt\")\n",
|
||||
"\n",
|
||||
"no_olympics_glyph = Text(x=7.5, y=1942, text=\"No Olympics in 1940 or 1944\",\n",
|
||||
" text_align=\"center\", text_baseline=\"middle\",\n",
|
||||
" text_font_size=\"9pt\", text_font_style=\"italic\", text_color=\"silver\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"xdr = Range1d(start=sprint.MetersBack.max()+2, end=0) # +2 is for padding\n",
|
||||
"ydr = DataRange1d(range_padding=0.05) \n",
|
||||
"\n",
|
||||
"plot = Plot(x_range=xdr, y_range=ydr, **plot_options)\n",
|
||||
"plot.title.text = \"Usain Bolt vs. 116 years of Olympic sprinters\"\n",
|
||||
"plot.add_glyph(source, medal_glyph)\n",
|
||||
"plot.add_glyph(source, athlete_glyph)\n",
|
||||
"plot.add_glyph(no_olympics_glyph)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"show(plot)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Adding Axes and Grids\n",
|
||||
"\n",
|
||||
"Next we add in models for the `Axis` and `Grids` that we would like to see. Since we want to exert more control over the appearance, we can choose specific tickers for the axes models to use (`SingleIntervalTicker` in this case). We add these guides to the plot using the `plot.add_layout` method. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.models import Grid, LinearAxis, SingleIntervalTicker"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"xdr = Range1d(start=sprint.MetersBack.max()+2, end=0) # +2 is for padding\n",
|
||||
"ydr = DataRange1d(range_padding=0.05) \n",
|
||||
"\n",
|
||||
"plot = Plot(x_range=xdr, y_range=ydr, **plot_options)\n",
|
||||
"plot.title.text = \"Usain Bolt vs. 116 years of Olympic sprinters\"\n",
|
||||
"plot.add_glyph(source, medal_glyph)\n",
|
||||
"plot.add_glyph(source, athlete_glyph)\n",
|
||||
"plot.add_glyph(no_olympics_glyph)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"xticker = SingleIntervalTicker(interval=5, num_minor_ticks=0)\n",
|
||||
"xaxis = LinearAxis(ticker=xticker, axis_line_color=None, major_tick_line_color=None,\n",
|
||||
" axis_label=\"Meters behind 2012 Bolt\", axis_label_text_font_size=\"10pt\", \n",
|
||||
" axis_label_text_font_style=\"bold\")\n",
|
||||
"plot.add_layout(xaxis, \"below\")\n",
|
||||
"\n",
|
||||
"xgrid = Grid(dimension=0, ticker=xaxis.ticker, grid_line_dash=\"dashed\")\n",
|
||||
"plot.add_layout(xgrid)\n",
|
||||
"\n",
|
||||
"yticker = SingleIntervalTicker(interval=12, num_minor_ticks=0)\n",
|
||||
"yaxis = LinearAxis(ticker=yticker, major_tick_in=-5, major_tick_out=10)\n",
|
||||
"plot.add_layout(yaxis, \"right\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"show(plot)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Adding a Hover Tool\n",
|
||||
"\n",
|
||||
"Finally we add a hover tool to display those extra columns that we put into our column data source. We use the template syntax for the tooltips, to have more control over the appearance. Tools can be added using the `plot.add_tools` method."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.models import HoverTool"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tooltips = \"\"\"\n",
|
||||
"<div>\n",
|
||||
" <span style=\"font-size: 15px;\">@Name</span> \n",
|
||||
" <span style=\"font-size: 10px; color: #666;\">(@Abbrev)</span>\n",
|
||||
"</div>\n",
|
||||
"<div>\n",
|
||||
" <span style=\"font-size: 17px; font-weight: bold;\">@Time{0.00}</span> \n",
|
||||
" <span style=\"font-size: 10px; color: #666;\">@Year</span>\n",
|
||||
"</div>\n",
|
||||
"<div style=\"font-size: 11px; color: #666;\">@{MetersBack}{0.00} meters behind</div>\n",
|
||||
"\"\"\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"xdr = Range1d(start=sprint.MetersBack.max()+2, end=0) # +2 is for padding\n",
|
||||
"ydr = DataRange1d(range_padding=0.05) \n",
|
||||
"\n",
|
||||
"plot = Plot(x_range=xdr, y_range=ydr, **plot_options)\n",
|
||||
"plot.title.text = \"Usain Bolt vs. 116 years of Olympic sprinters\"\n",
|
||||
"medal = plot.add_glyph(source, medal_glyph) # we need this renderer to configure the hover tool\n",
|
||||
"plot.add_glyph(source, athlete_glyph)\n",
|
||||
"plot.add_glyph(no_olympics_glyph)\n",
|
||||
"\n",
|
||||
"xticker = SingleIntervalTicker(interval=5, num_minor_ticks=0)\n",
|
||||
"xaxis = LinearAxis(ticker=xticker, axis_line_color=None, major_tick_line_color=None,\n",
|
||||
" axis_label=\"Meters behind 2012 Bolt\", axis_label_text_font_size=\"10pt\", \n",
|
||||
" axis_label_text_font_style=\"bold\")\n",
|
||||
"plot.add_layout(xaxis, \"below\")\n",
|
||||
"\n",
|
||||
"xgrid = Grid(dimension=0, ticker=xaxis.ticker, grid_line_dash=\"dashed\")\n",
|
||||
"plot.add_layout(xgrid)\n",
|
||||
"\n",
|
||||
"yticker = SingleIntervalTicker(interval=12, num_minor_ticks=0)\n",
|
||||
"yaxis = LinearAxis(ticker=yticker, major_tick_in=-5, major_tick_out=10)\n",
|
||||
"plot.add_layout(yaxis, \"right\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"hover = HoverTool(tooltips=tooltips, renderers=[medal])\n",
|
||||
"plot.add_tools(hover)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"show(plot)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Exercises"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Custom User Models\n",
|
||||
"\n",
|
||||
"It is possible to extend the set of built-in Bokeh models with your own custom user models. The capability opens some valuable use-cases:\n",
|
||||
"* customizing existing Bokeh model behaviour\n",
|
||||
"* wrapping and connecting other JS libraries to Bokeh\n",
|
||||
"\n",
|
||||
"With this capability, advanced users can try out new features or techniques easily, without having to set up a full Bokeh development environment. \n",
|
||||
"\n",
|
||||
"The section gives a basi outline of a custom model starts with a JavaScript implementation, which subclasses an existing BokehJS model. Full details can be found in the [Extending Bokeh](https://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html) chapter of the User's Guide."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Implement the JavaScript Model"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"CODE = \"\"\"\n",
|
||||
"import {UIElement, UIElementView} from \"models/ui/ui_element\"\n",
|
||||
"import {Slider} from \"models/widgets/slider\"\n",
|
||||
"import {div} from \"core/dom\"\n",
|
||||
"import * as p from \"core/properties\"\n",
|
||||
"\n",
|
||||
"export class CustomView extends UIElementView {\n",
|
||||
" model: Custom\n",
|
||||
"\n",
|
||||
" private content_el: HTMLElement\n",
|
||||
"\n",
|
||||
" override connect_signals(): void {\n",
|
||||
" super.connect_signals()\n",
|
||||
" this.connect(this.model.slider.change, () => this._update_text())\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" override render(): void {\n",
|
||||
" // BokehJS views create <div> elements by default. These are accessible\n",
|
||||
" // as ``this.el``. Many Bokeh views ignore the default <div> and\n",
|
||||
" // instead do things like draw to the HTML canvas. In this case though,\n",
|
||||
" // the program changes the contents of the <div> based on the current\n",
|
||||
" // slider value.\n",
|
||||
" super.render()\n",
|
||||
"\n",
|
||||
" this.content_el = div({style: {\n",
|
||||
" textAlign: \"center\",\n",
|
||||
" fontSize: \"1.2em\",\n",
|
||||
" padding: \"2px\",\n",
|
||||
" color: \"#b88d8e\",\n",
|
||||
" backgroundColor: \"#2a3153\",\n",
|
||||
" }})\n",
|
||||
" this.shadow_el.appendChild(this.content_el)\n",
|
||||
"\n",
|
||||
" this._update_text()\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" private _update_text(): void {\n",
|
||||
" this.content_el.textContent = `${this.model.text}: ${this.model.slider.value}`\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"export namespace Custom {\n",
|
||||
" export type Attrs = p.AttrsOf<Props>\n",
|
||||
"\n",
|
||||
" export type Props = UIElement.Props & {\n",
|
||||
" text: p.Property<string>\n",
|
||||
" slider: p.Property<Slider>\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"export interface Custom extends Custom.Attrs {}\n",
|
||||
"\n",
|
||||
"export class Custom extends UIElement {\n",
|
||||
" properties: Custom.Props\n",
|
||||
" __view_type__: CustomView\n",
|
||||
"\n",
|
||||
" constructor(attrs?: Partial<Custom.Attrs>) {\n",
|
||||
" super(attrs)\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" static {\n",
|
||||
" // If there is an associated view, this is typically boilerplate.\n",
|
||||
" this.prototype.default_view = CustomView\n",
|
||||
"\n",
|
||||
" // The this.define() block adds corresponding \"properties\" to the JS\n",
|
||||
" // model. These should normally line up 1-1 with the Python model\n",
|
||||
" // class. Most property types have counterparts. For example,\n",
|
||||
" // bokeh.core.properties.String will correspond to ``String`` in the\n",
|
||||
" // JS implementation. Where JS lacks a given type, you can use\n",
|
||||
" // ``p.Any`` as a \"wildcard\" property type.\n",
|
||||
" this.define<Custom.Props>(({String, Ref}) => ({\n",
|
||||
" text: [ String, \"Custom text\" ],\n",
|
||||
" slider: [ Ref(Slider) ],\n",
|
||||
" }))\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\"\"\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Define the Python Model\n",
|
||||
"\n",
|
||||
"This JavaScript implementation is then attached to a corresponding Python Bokeh model:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.core.properties import Instance, Required, String\n",
|
||||
"\n",
|
||||
"class Custom(UIElement):\n",
|
||||
"\n",
|
||||
" __implementation__ = TypeScript(CODE)\n",
|
||||
"\n",
|
||||
" text = String(default=\"Custom text\")\n",
|
||||
"\n",
|
||||
" slider = Required(Instance(Slider))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Use the Python Model\n",
|
||||
"\n",
|
||||
"Then the new model can be used seamlessly in the same way as any built-in Bokeh model:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from bokeh.io import show, output_file\n",
|
||||
"from bokeh.layouts import column\n",
|
||||
"from bokeh.models import Slider\n",
|
||||
"\n",
|
||||
"slider = Slider(start=0, end=10, step=0.1, value=0, title=\"value\")\n",
|
||||
"\n",
|
||||
"custom = Custom(text=\"Special Slider Display\", slider=slider)\n",
|
||||
"\n",
|
||||
"layout = column(slider, custom)\n",
|
||||
"\n",
|
||||
"show(layout)\n",
|
||||
"\n",
|
||||
"# Necessary to explicitly reload BokehJS to pick up new extension code\n",
|
||||
"output_notebook()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"show(layout)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Next Section"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To explore the next topic in the appendices, click on this link: [A2 - Visualizing Big Data with Datashader](A2%20-%20Visualizing%20Big%20Data%20with%20Datashader.ipynb)\n",
|
||||
"\n",
|
||||
"To go back to the overview, click [here](00%20-%20Introduction%20and%20Setup.ipynb)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"anaconda-cloud": {},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.13"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,171 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table style=\"float:left; border:none\">\n",
|
||||
" <tr style=\"border:none\">\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <a href=\"https://bokeh.org/\"> \n",
|
||||
" <img \n",
|
||||
" src=\"assets/bokeh-transparent.png\" \n",
|
||||
" style=\"width:50px\"\n",
|
||||
" >\n",
|
||||
" </a> \n",
|
||||
" </td>\n",
|
||||
" <td style=\"border:none\">\n",
|
||||
" <h1>Bokeh Tutorial</h1>\n",
|
||||
" </td>\n",
|
||||
" </tr>\n",
|
||||
"</table>\n",
|
||||
"<div style=\"float:right;\"><h2>A4. Additional resources</h2></div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Additional resources\n",
|
||||
"\n",
|
||||
"There are lots of things we haven't had time to tell you about. In general to learn more about bokeh, the following resources will hopefully be helpful:\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Doumentation\n",
|
||||
"\n",
|
||||
"##### Main Page - https://bokeh.org \n",
|
||||
"\n",
|
||||
"The main front page, with links to many other resources\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"##### Documentation - https://docs.bokeh.org/en/latest \n",
|
||||
"\n",
|
||||
"The documentation toplevel page\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"##### User's Guide - https://docs.bokeh.org/en/latest/docs/user_guide.html\n",
|
||||
"\n",
|
||||
"The user's guide has many top-oriented subsections, for example \"Plotting with Basic Glyphs\", \"Configuring Plot Tools\", or \"Adding Interactions\". Each user's guide section typically example code and corresponding live plots that demonstrate how to accomplish various tasks. \n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"##### Gallery - https://docs.bokeh.org/en/latest/docs/gallery.html\n",
|
||||
"\n",
|
||||
"One of the best ways to learn is to find an existing example similar to what you want, and to study it and then use it as a starting place. Starting from a known working example can often save time and effort when getting started by allowing you to make small, incremental changes and observing the outcome. The Bokeh docs have a large thumbnail gallery that links to live plots and apps with corresponding code. \n",
|
||||
"\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"##### Reference Guide - https://docs.bokeh.org/en/latest/docs/reference.html\n",
|
||||
"\n",
|
||||
"If you are already familiar with Bokeh and have questions about specific details of the obejcts you are already using, the reference guide is a good resource for finding information. The reference guide is automatically generated from the project source code and is a complete resources for all bokeh models and their properties. \n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"##### Issue tracker - https://github.com/bokeh/bokeh/issues\n",
|
||||
"\n",
|
||||
"The GitHub issue tracker is the place to go to submit ***bug reports*** and ***feature requests***. It it NOT the right place for general support questions (see the *General Community Support* links below).\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Example apps and Scripts\n",
|
||||
"\n",
|
||||
"In addition to all the live gallery examples, Bokeh has many additional scripts and apps that can be instructive to study and emulate. \n",
|
||||
"\n",
|
||||
"##### Examples folder - https://github.com/bokeh/bokeh/tree/master/examples/\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## General Commnity Support\n",
|
||||
"\n",
|
||||
"Bokeh has a large and growing community. The best place to go for general support questions (either to ask, or to answer!) is https://discourse.bokeh.org\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Contributor Resources\n",
|
||||
"\n",
|
||||
"Bokeh has a small but growing developer community. We are always looking to have new contributors. Below are some resources for people involved in working on Bokeh itself.\n",
|
||||
"\n",
|
||||
"##### Source code - https://github.com/bokeh/bokeh\n",
|
||||
"\n",
|
||||
"Go here to clone the GitHub repo (in order to contribute or get the examples), or to submit issues to the issue tracker \n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"##### Issue tracker - https://github.com/bokeh/bokeh/issues\n",
|
||||
"\n",
|
||||
"The GitHub issue tracker is the place to go to submit ***bug reports*** and ***feature requests***. For general support questions, see the *General Community Support* links above.\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"#### Contributors's Guide - https://bokeh.pydata.org/en/latest/docs/dev_guide.html\n",
|
||||
"\n",
|
||||
"If you are interesting in becoming a contributor to Bokeh, the developer's guide is the place to start. It has information about getting a development environment set up, the library architecture, writing and running tests, \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Next Section"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This is the last section of the appendices.\n",
|
||||
"\n",
|
||||
"To go back to the overview, click [here](00%20-%20Introduction%20and%20Setup.ipynb)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.8"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
## Clone or download the repo
|
||||
First get local copies of the tutorial notebooks:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/bokeh/bokeh-notebooks.git
|
||||
```
|
||||
|
||||
Or download from: https://github.com/bokeh/bokeh-notebooks/archive/master.zip
|
||||
|
||||
## Install the dependencies
|
||||
|
||||
This tutorial has been tested on:
|
||||
|
||||
* bokeh 3.0.0
|
||||
* pandas 1.4.4
|
||||
* notebook 6.5.1
|
||||
* pillow 9.2.0
|
||||
* selenium 3.141.0
|
||||
|
||||
Other combinations may work also.
|
||||
|
||||
The quickest, easiest way to install is to use Anaconda (or Miniconda):
|
||||
|
||||
#### Installing with anaconda
|
||||
|
||||
Install [anaconda](http://anaconda.com/downloads)
|
||||
|
||||
Anaconda should come with all the dependencies included, but you may need to update your versions.
|
||||
|
||||
#### Installing with miniconda
|
||||
|
||||
Install [miniconda](http://conda.pydata.org/miniconda.html).
|
||||
|
||||
Use the command line to create an environment and install the packages:
|
||||
|
||||
```bash
|
||||
$ conda env create
|
||||
$ source activate bokeh-notebooks
|
||||
```
|
||||
|
||||
NOTE: Run this in the `tutorial` directory where `environment.yml` file is.
|
||||
|
||||
----
|
||||
|
||||
Once you've got a base install, you can install the remaining dependencies with:
|
||||
|
||||
```bash
|
||||
conda install phantomjs pillow selenium
|
||||
```
|
||||
|
||||
## Get the sample data
|
||||
|
||||
Bokeh has a [sample data](https://docs.bokeh.org/en/latest/docs/installation.html#sample-data) download that gives us some data to build demo visualizations. To get
|
||||
it run the following command at your command line:
|
||||
|
||||
```bash
|
||||
$ bokeh sampledata
|
||||
```
|
||||
|
||||
or run the following from within a Python interpreter:
|
||||
|
||||
```python
|
||||
import bokeh.sampledata
|
||||
bokeh.sampledata.download()
|
||||
```
|
||||
|
||||
### Install Datashader and Holoviews (optional)
|
||||
|
||||
Some optional sections require the additional packages Flask, Datashader, and Holoviews.
|
||||
These can be installed with:
|
||||
|
||||
```bash
|
||||
$ conda install -c pyviz datashader holoviews flask
|
||||
```
|
||||
|
||||
## Run the Jupyter notebook
|
||||
|
||||
From this folder run jupyter notebook, and open the [00 - Introduction and Setup.ipynb](00 - Introduction and Setup.ipynb) notebook.
|
||||
|
||||
```
|
||||
$ jupyter notebook
|
||||
```
|
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/5_gaussians_3_ways.png
(Stored with Git LFS)
Normal file
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/5_gaussians_3_ways.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/5_gaussians_dsblue.png
(Stored with Git LFS)
Normal file
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/5_gaussians_dsblue.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/5_gaussians_labeled.png
(Stored with Git LFS)
Normal file
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/5_gaussians_labeled.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/bokeh-transparent.png
(Stored with Git LFS)
Normal file
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/bokeh-transparent.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/datashader_examples.png
(Stored with Git LFS)
Normal file
BIN
Man1130/jupyter/Man1130-python-comission/tryout/jupyterlab-bokeh-helloworld/bokeh-notebooks/tutorial/assets/datashader_examples.png
(Stored with Git LFS)
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 27 KiB |
@@ -0,0 +1,8 @@
|
||||
name: bokeh-notebooks
|
||||
dependencies:
|
||||
- python
|
||||
- bokeh=0.12.2
|
||||
- pandas
|
||||
- jupyter
|
||||
- nodejs
|
||||
- ipywidgets
|
Reference in New Issue
Block a user