diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..eccabec
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,48 @@
+name: Build and deploy to github pages
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - '*'
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.13'
+ - name: Install the dependencies
+ run: |
+ python -m pip install -r requirements.txt
+ - name: Build the JupyterLite site
+ run: |
+ jupyter lite build --contents notebooks --output-dir dist
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ./dist
+
+ deploy:
+ needs: build
+ #if: github.ref == 'refs/heads/main'
+ permissions:
+ pages: write
+ id-token: write
+
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+
+ runs-on: ubuntu-latest
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index 1f565fd..c26e4c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -134,3 +134,7 @@ dmypy.json
# Pyre type checker
.pyre/
+
+# JupyterLite deployment
+.jupyterlite.doit.db
+_output/
diff --git a/data/__init__.py b/.nojekyll
similarity index 100%
rename from data/__init__.py
rename to .nojekyll
diff --git a/README.md b/README.md
index 37894bc..6ad075c 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,22 @@
+# Work in progress to use pyodide kernel in JupyterLite for tutorial
+
+Deployed to github pages at https://bokeh.github.io/tutorial
+
+To try out locally, create a python virtual environment of your choice (`venv`, `pyenv`,
+'mamba', `conda`, etc) and follow these steps:
+
+```bash
+python -m pip install -r requirements.txt
+jupyter lite build --contents notebooks
+jupyter lite serve
+```
+
+and open a web browser at the URL specified.
+
+------------------------
+
+
+
# Bokeh tutorial notebooks
## Setup and run the tutorials
diff --git a/environment.yml b/environment.yml
deleted file mode 100644
index 7c123f5..0000000
--- a/environment.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: bk-tutorial
-channels:
- - conda-forge
-dependencies:
- - python>=3.12
- - pip
- - geojson
- - geopandas
- - jupyter_client<8
- - notebook
- - pandas
- - pyshp
- - ipykernel
- - pip:
- - bokeh==3.5
- - bokeh_sampledata
diff --git a/notebooks/01_introduction.ipynb b/notebooks/01_introduction.ipynb
index 646473b..d13d6ef 100644
--- a/notebooks/01_introduction.ipynb
+++ b/notebooks/01_introduction.ipynb
@@ -127,7 +127,9 @@
"metadata": {},
"outputs": [],
"source": [
- "# load and display tutorial dashboard\n",
+ "# Install geopandas into pyodide environment running in browser\n",
+ "%pip install -q geopandas\n",
+ "\n",
"from tutorial_dashboard import dashboard_layout\n",
"\n",
"show(dashboard_layout)"
@@ -245,7 +247,7 @@
"Python script.\n",
"This tutorial will reference the data preparation script but will not go into detail\n",
"about the data preparation itself.\n",
- "You can find the data processing code in [`carriers_data.py`](../data/carriers_data.py).\n",
+ "You can find the data processing code in [`carriers_data.py`](./data/carriers_data.py).\n",
"\n",
"This tutorial is designed to run on [mybinder.org](https://mybinder.readthedocs.io/en/latest/).\n",
"You can also run this tutorial locally on your computer.\n",
@@ -286,7 +288,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
" \n",
"\n",
"\n",
diff --git a/notebooks/02_installation_and_setup.ipynb b/notebooks/02_installation_and_setup.ipynb
index 4c78c47..a1e2ee9 100644
--- a/notebooks/02_installation_and_setup.ipynb
+++ b/notebooks/02_installation_and_setup.ipynb
@@ -117,7 +117,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/03_basic_concepts.ipynb b/notebooks/03_basic_concepts.ipynb
index 6c8cb7d..865b451 100644
--- a/notebooks/03_basic_concepts.ipynb
+++ b/notebooks/03_basic_concepts.ipynb
@@ -256,7 +256,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/04_basic_plots.ipynb b/notebooks/04_basic_plots.ipynb
index db22639..16ae546 100644
--- a/notebooks/04_basic_plots.ipynb
+++ b/notebooks/04_basic_plots.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -525,7 +526,7 @@
"This is an example of how you can customize the appearance of the different\n",
"elements of your plot.\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/05_styling.ipynb b/notebooks/05_styling.ipynb
index 20905cc..d261cc5 100644
--- a/notebooks/05_styling.ipynb
+++ b/notebooks/05_styling.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -749,7 +750,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/06_data_sources.ipynb b/notebooks/06_data_sources.ipynb
index 9b6de1f..55a2f58 100644
--- a/notebooks/06_data_sources.ipynb
+++ b/notebooks/06_data_sources.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -456,7 +457,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/07_annotations.ipynb b/notebooks/07_annotations.ipynb
index df90c38..f0ac1ab 100644
--- a/notebooks/07_annotations.ipynb
+++ b/notebooks/07_annotations.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -613,7 +614,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/08_plot_tools.ipynb b/notebooks/08_plot_tools.ipynb
index dd001d4..bd9b806 100644
--- a/notebooks/08_plot_tools.ipynb
+++ b/notebooks/08_plot_tools.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -543,7 +544,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/09_more_plot_types.ipynb b/notebooks/09_more_plot_types.ipynb
index 0d6e293..97a65b1 100644
--- a/notebooks/09_more_plot_types.ipynb
+++ b/notebooks/09_more_plot_types.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -173,6 +174,8 @@
"metadata": {},
"outputs": [],
"source": [
+ "%pip install -q geojson geopandas shapely\n",
+ "\n",
"from shapely.geometry import Point\n",
"from pyproj import CRS, Transformer\n",
"import geojson\n",
@@ -309,8 +312,8 @@
"metadata": {},
"outputs": [],
"source": [
- "states_gdf = gpd.read_file(\"../data/us-states.geojson\")\n",
- "states_gdf.plot() # use geopandas to plot the state shapes"
+ "states_gdf = gpd.read_file(\"./data/us-states.geojson\")\n",
+ "states_gdf.head()"
]
},
{
@@ -376,7 +379,7 @@
"from bokeh.transform import linear_cmap\n",
"\n",
"# read the GeoJSON file containing the state shapes\n",
- "states_gdf = gpd.read_file(\"../data/us-states.geojson\")\n",
+ "states_gdf = gpd.read_file(\"./data/us-states.geojson\")\n",
"# read the pre-processed data frame from the demo data set and join it to the state shapes\n",
"states_gdf = states_gdf.join(data.get_states_routes_df(), on=states_gdf[\"Name\"])\n",
"# create the GeoJSONDataSource\n",
@@ -852,7 +855,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/10_layouts.ipynb b/notebooks/10_layouts.ipynb
index 3c2e0bd..8e6d6b9 100644
--- a/notebooks/10_layouts.ipynb
+++ b/notebooks/10_layouts.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -405,7 +406,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/11_widgets_interactivity.ipynb b/notebooks/11_widgets_interactivity.ipynb
index 81f4db7..59a986b 100644
--- a/notebooks/11_widgets_interactivity.ipynb
+++ b/notebooks/11_widgets_interactivity.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -287,6 +288,8 @@
"metadata": {},
"outputs": [],
"source": [
+ "%pip install -q bokeh-sampledata\n",
+ "\n",
"import pandas as pd\n",
"\n",
"from bokeh.palettes import Spectral4\n",
@@ -1206,7 +1209,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/12_demo_dashboard.ipynb b/notebooks/12_demo_dashboard.ipynb
index cb6f79e..549d376 100644
--- a/notebooks/12_demo_dashboard.ipynb
+++ b/notebooks/12_demo_dashboard.ipynb
@@ -30,6 +30,7 @@
"outputs": [],
"source": [
"# load tutorial data\n",
+ "%pip install -q pandas\n",
"from tutorial_data import data"
]
},
@@ -1218,10 +1219,11 @@
"metadata": {},
"outputs": [],
"source": [
+ "%pip install -q geopandas\n",
"import geopandas as gpd\n",
"\n",
- "states_gdf = gpd.read_file(\"../data/us-states.geojson\")\n",
- "states_gdf.plot() # use geopandas to plot the state shapes"
+ "states_gdf = gpd.read_file(\"./data/us-states.geojson\")\n",
+ "states_gdf.head(2)"
]
},
{
@@ -1316,7 +1318,7 @@
"outputs": [],
"source": [
"# read the geojson file containing the state shapes\n",
- "states_gdf = gpd.read_file(\"../data/us-states.geojson\")\n",
+ "states_gdf = gpd.read_file(\"./data/us-states.geojson\")\n",
"# read the pre-processed data frame from the demo data set and join it to the state shapes\n",
"states_gdf = states_gdf.join(data.get_states_routes_df(), on=states_gdf[\"Name\"])\n",
"# create the GeoJSONDataSource\n",
@@ -1483,7 +1485,7 @@
"from bokeh.transform import linear_cmap\n",
"\n",
"# read the geojson file containing the state shapes\n",
- "states_gdf = gpd.read_file(\"../data/us-states.geojson\")\n",
+ "states_gdf = gpd.read_file(\"./data/us-states.geojson\")\n",
"# read the pre-processed data frame from the demo data set and join it to the state shapes\n",
"states_gdf = states_gdf.join(data.get_states_routes_df(), on=states_gdf[\"Name\"])\n",
"# create the GeoJSONDataSource\n",
@@ -1578,7 +1580,7 @@
"For details about how to compute the angles, see the detailed example in the\n",
"[Wedge plots section](09_more_plot_types.ipynb#Wedge-plots).\n",
"For the specific code generating these DataFrames, see the function\n",
- "``get_top_carriers_by_metrics`` in [carriers_data.py](../data/carriers_data.py)."
+ "``get_top_carriers_by_metrics`` in [carriers_data.py](./data/carriers_data.py)."
]
},
{
@@ -1898,7 +1900,7 @@
"source": [
"# Next section\n",
"\n",
- "\n",
+ "\n",
"
\n",
"\n",
"\n",
diff --git a/notebooks/13_exporting_embedding.ipynb b/notebooks/13_exporting_embedding.ipynb
index 3d3ceb0..10cd14b 100644
--- a/notebooks/13_exporting_embedding.ipynb
+++ b/notebooks/13_exporting_embedding.ipynb
@@ -91,15 +91,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "
\n", - " ✨ The HTML output file of the complete dashboard is hosted at: bokeh.github.io/tutorial ↗️\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "The HTML file is saved with the name `custom_filename.html` and appears in the file browser on the left.\n", + "Double-click it to open it; you may have to confirm that you trust the file contents depending on your browser and privacy settings.\n", + "\n", "Calling `output_file` **switches Bokeh to file output mode persistently**.\n", "This means that all subsequent calls to `show` will generate output to the specified file.\n", "\n", @@ -334,7 +328,7 @@ "source": [ "# Next section\n", "\n", - "\n", + "\n", "