Initial commit

This commit is contained in:
Peter 2023-06-24 01:19:43 +08:00 committed by GitHub
commit 4f010cec32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 6534 additions and 0 deletions

48
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,48 @@
name: Build and Deploy
on:
push:
branches:
- main
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install the dependencies
run: |
python -m pip install -r requirements.txt
- name: Build the JupyterLite site
run: |
cp README.md content
jupyter lite build --contents content --output-dir dist
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
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@v1

116
.gitignore vendored Normal file
View File

@ -0,0 +1,116 @@
*.bundle.*
lib/
node_modules/
.yarn-packages/
*.egg-info/
.ipynb_checkpoints
*.tsbuildinfo
# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# OS X stuff
*.DS_Store
# End of https://www.gitignore.io/api/python
# jupyterlite
*.doit.db
_output

1
.nojekyll Normal file
View File

@ -0,0 +1 @@

29
README.md Normal file
View File

@ -0,0 +1,29 @@
# JupyterLite Demo
[![lite-badge](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://jupyterlite.github.io/demo)
JupyterLite deployed as a static site to GitHub Pages, for demo purposes.
## ✨ Try it in your browser ✨
➡️ **https://jupyterlite.github.io/demo**
![github-pages](https://user-images.githubusercontent.com/591645/120649478-18258400-c47d-11eb-80e5-185e52ff2702.gif)
## Requirements
JupyterLite is being tested against modern web browsers:
- Firefox 90+
- Chromium 89+
## Deploy your JupyterLite website on GitHub Pages
Check out the guide on the JupyterLite documentation: https://jupyterlite.readthedocs.io/en/latest/quickstart/deploy.html
## Further Information and Updates
For more info, keep an eye on the JupyterLite documentation:
- How-to Guides: https://jupyterlite.readthedocs.io/en/latest/howto/index.html
- Reference: https://jupyterlite.readthedocs.io/en/latest/reference/index.html

File diff suppressed because one or more lines are too long

54
content/data/bar.vl.json Normal file
View File

@ -0,0 +1,54 @@
{
"data": {
"values": [
{
"a": "A",
"b": 28
},
{
"a": "B",
"b": 55
},
{
"a": "C",
"b": 43
},
{
"a": "D",
"b": 91
},
{
"a": "E",
"b": 81
},
{
"a": "F",
"b": 53
},
{
"a": "G",
"b": 19
},
{
"a": "H",
"b": 87
},
{
"a": "I",
"b": 52
}
]
},
"description": "A simple bar chart with embedded data.",
"encoding": {
"x": {
"field": "a",
"type": "ordinal"
},
"y": {
"field": "b",
"type": "quantitative"
}
},
"mark": "bar"
}

View File

@ -0,0 +1,8 @@
>SEQUENCE_1
MTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKADRLAAEG
LVSVKVSDDFTIAAMRPSYLSYEDLDMTFVENEYKALVAELEKENEERRRLKDPNKPEHK
IPQFASRKQLSDAILKEAEEKIKEELKAQGKPEKIWDNIIPGKMNSFIADNSQLDSKLTL
MGQFYVMDDKKTVEQVIAEKEKEFGGKIKIVEFICFEVGEGLEKKTEDFAAEVAAQL
>SEQUENCE_2
SATVSEINSETDFVAKNDQFIALTKDTTAHIQSNSLQSVEELHSSTINGVKFEEYLKSQI
ATIGENLVVRRFATLKAGANGVVNGYIHTNGRVGVVIAAACDSAEVASKSRDLLRQICMH

151
content/data/iris.csv Normal file
View File

@ -0,0 +1,151 @@
sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,se
4.9,3,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5,3.6,1.4,0.2,setosa
5.4,3.9,1.7,0.4,setosa
4.6,3.4,1.4,0.3,setosa
5,3.4,1.5,0.2,setosa
4.4,2.9,1.4,0.2,setosa
4.9,3.1,1.5,0.1,setosa
5.4,3.7,1.5,0.2,setosa
4.8,3.4,1.6,0.2,setosa
4.8,3,1.4,0.1,setosa
4.3,3,1.1,0.1,setosa
5.8,4,1.2,0.2,setosa
5.7,4.4,1.5,0.4,setosa
5.4,3.9,1.3,0.4,setosa
5.1,3.5,1.4,0.3,setosa
5.7,3.8,1.7,0.3,setosa
5.1,3.8,1.5,0.3,setosa
5.4,3.4,1.7,0.2,setosa
5.1,3.7,1.5,0.4,setosa
4.6,3.6,1,0.2,setosa
5.1,3.3,1.7,0.5,setosa
4.8,3.4,1.9,0.2,setosa
5,3,1.6,0.2,setosa
5,3.4,1.6,0.4,setosa
5.2,3.5,1.5,0.2,setosa
5.2,3.4,1.4,0.2,setosa
4.7,3.2,1.6,0.2,setosa
4.8,3.1,1.6,0.2,setosa
5.4,3.4,1.5,0.4,setosa
5.2,4.1,1.5,0.1,setosa
5.5,4.2,1.4,0.2,setosa
4.9,3.1,1.5,0.1,setosa
5,3.2,1.2,0.2,setosa
5.5,3.5,1.3,0.2,setosa
4.9,3.1,1.5,0.1,setosa
4.4,3,1.3,0.2,setosa
5.1,3.4,1.5,0.2,setosa
5,3.5,1.3,0.3,setosa
4.5,2.3,1.3,0.3,setosa
4.4,3.2,1.3,0.2,setosa
5,3.5,1.6,0.6,setosa
5.1,3.8,1.9,0.4,setosa
4.8,3,1.4,0.3,setosa
5.1,3.8,1.6,0.2,setosa
4.6,3.2,1.4,0.2,setosa
5.3,3.7,1.5,0.2,setosa
5,3.3,1.4,0.2,setosa
7,3.2,4.7,1.4,versicolor
6.4,3.2,4.5,1.5,versicolor
6.9,3.1,4.9,1.5,versicolor
5.5,2.3,4,1.3,versicolor
6.5,2.8,4.6,1.5,versicolor
5.7,2.8,4.5,1.3,versicolor
6.3,3.3,4.7,1.6,versicolor
4.9,2.4,3.3,1,versicolor
6.6,2.9,4.6,1.3,versicolor
5.2,2.7,3.9,1.4,versicolor
5,2,3.5,1,versicolor
5.9,3,4.2,1.5,versicolor
6,2.2,4,1,versicolor
6.1,2.9,4.7,1.4,versicolor
5.6,2.9,3.6,1.3,versicolor
6.7,3.1,4.4,1.4,versicolor
5.6,3,4.5,1.5,versicolor
5.8,2.7,4.1,1,versicolor
6.2,2.2,4.5,1.5,versicolor
5.6,2.5,3.9,1.1,versicolor
5.9,3.2,4.8,1.8,versicolor
6.1,2.8,4,1.3,versicolor
6.3,2.5,4.9,1.5,versicolor
6.1,2.8,4.7,1.2,versicolor
6.4,2.9,4.3,1.3,versicolor
6.6,3,4.4,1.4,versicolor
6.8,2.8,4.8,1.4,versicolor
6.7,3,5,1.7,versicolor
6,2.9,4.5,1.5,versicolor
5.7,2.6,3.5,1,versicolor
5.5,2.4,3.8,1.1,versicolor
5.5,2.4,3.7,1,versicolor
5.8,2.7,3.9,1.2,versicolor
6,2.7,5.1,1.6,versicolor
5.4,3,4.5,1.5,versicolor
6,3.4,4.5,1.6,versicolor
6.7,3.1,4.7,1.5,versicolor
6.3,2.3,4.4,1.3,versicolor
5.6,3,4.1,1.3,versicolor
5.5,2.5,4,1.3,versicolor
5.5,2.6,4.4,1.2,versicolor
6.1,3,4.6,1.4,versicolor
5.8,2.6,4,1.2,versicolor
5,2.3,3.3,1,versicolor
5.6,2.7,4.2,1.3,versicolor
5.7,3,4.2,1.2,versicolor
5.7,2.9,4.2,1.3,versicolor
6.2,2.9,4.3,1.3,versicolor
5.1,2.5,3,1.1,versicolor
5.7,2.8,4.1,1.3,versicolor
6.3,3.3,6,2.5,virginica
5.8,2.7,5.1,1.9,virginica
7.1,3,5.9,2.1,virginica
6.3,2.9,5.6,1.8,virginica
6.5,3,5.8,2.2,virginica
7.6,3,6.6,2.1,virginica
4.9,2.5,4.5,1.7,virginica
7.3,2.9,6.3,1.8,virginica
6.7,2.5,5.8,1.8,virginica
7.2,3.6,6.1,2.5,virginica
6.5,3.2,5.1,2,virginica
6.4,2.7,5.3,1.9,virginica
6.8,3,5.5,2.1,virginica
5.7,2.5,5,2,virginica
5.8,2.8,5.1,2.4,virginica
6.4,3.2,5.3,2.3,virginica
6.5,3,5.5,1.8,virginica
7.7,3.8,6.7,2.2,virginica
7.7,2.6,6.9,2.3,virginica
6,2.2,5,1.5,virginica
6.9,3.2,5.7,2.3,virginica
5.6,2.8,4.9,2,virginica
7.7,2.8,6.7,2,virginica
6.3,2.7,4.9,1.8,virginica
6.7,3.3,5.7,2.1,virginica
7.2,3.2,6,1.8,virginica
6.2,2.8,4.8,1.8,virginica
6.1,3,4.9,1.8,virginica
6.4,2.8,5.6,2.1,virginica
7.2,3,5.8,1.6,virginica
7.4,2.8,6.1,1.9,virginica
7.9,3.8,6.4,2,virginica
6.4,2.8,5.6,2.2,virginica
6.3,2.8,5.1,1.5,virginica
6.1,2.6,5.6,1.4,virginica
7.7,3,6.1,2.3,virginica
6.3,3.4,5.6,2.4,virginica
6.4,3.1,5.5,1.8,virginica
6,3,4.8,1.8,virginica
6.9,3.1,5.4,2.1,virginica
6.7,3.1,5.6,2.4,virginica
6.9,3.1,5.1,2.3,virginica
5.8,2.7,5.1,1.9,virginica
6.8,3.2,5.9,2.3,virginica
6.7,3.3,5.7,2.5,virginica
6.7,3,5.2,2.3,virginica
6.3,2.5,5,1.9,virginica
6.5,3,5.2,2,virginica
6.2,3.4,5.4,2.3,virginica
5.9,3,5.1,1.8,virginica
1 sepal_length sepal_width petal_length petal_width species
2 5.1 3.5 1.4 0.2 se
3 4.9 3 1.4 0.2 setosa
4 4.7 3.2 1.3 0.2 setosa
5 4.6 3.1 1.5 0.2 setosa
6 5 3.6 1.4 0.2 setosa
7 5.4 3.9 1.7 0.4 setosa
8 4.6 3.4 1.4 0.3 setosa
9 5 3.4 1.5 0.2 setosa
10 4.4 2.9 1.4 0.2 setosa
11 4.9 3.1 1.5 0.1 setosa
12 5.4 3.7 1.5 0.2 setosa
13 4.8 3.4 1.6 0.2 setosa
14 4.8 3 1.4 0.1 setosa
15 4.3 3 1.1 0.1 setosa
16 5.8 4 1.2 0.2 setosa
17 5.7 4.4 1.5 0.4 setosa
18 5.4 3.9 1.3 0.4 setosa
19 5.1 3.5 1.4 0.3 setosa
20 5.7 3.8 1.7 0.3 setosa
21 5.1 3.8 1.5 0.3 setosa
22 5.4 3.4 1.7 0.2 setosa
23 5.1 3.7 1.5 0.4 setosa
24 4.6 3.6 1 0.2 setosa
25 5.1 3.3 1.7 0.5 setosa
26 4.8 3.4 1.9 0.2 setosa
27 5 3 1.6 0.2 setosa
28 5 3.4 1.6 0.4 setosa
29 5.2 3.5 1.5 0.2 setosa
30 5.2 3.4 1.4 0.2 setosa
31 4.7 3.2 1.6 0.2 setosa
32 4.8 3.1 1.6 0.2 setosa
33 5.4 3.4 1.5 0.4 setosa
34 5.2 4.1 1.5 0.1 setosa
35 5.5 4.2 1.4 0.2 setosa
36 4.9 3.1 1.5 0.1 setosa
37 5 3.2 1.2 0.2 setosa
38 5.5 3.5 1.3 0.2 setosa
39 4.9 3.1 1.5 0.1 setosa
40 4.4 3 1.3 0.2 setosa
41 5.1 3.4 1.5 0.2 setosa
42 5 3.5 1.3 0.3 setosa
43 4.5 2.3 1.3 0.3 setosa
44 4.4 3.2 1.3 0.2 setosa
45 5 3.5 1.6 0.6 setosa
46 5.1 3.8 1.9 0.4 setosa
47 4.8 3 1.4 0.3 setosa
48 5.1 3.8 1.6 0.2 setosa
49 4.6 3.2 1.4 0.2 setosa
50 5.3 3.7 1.5 0.2 setosa
51 5 3.3 1.4 0.2 setosa
52 7 3.2 4.7 1.4 versicolor
53 6.4 3.2 4.5 1.5 versicolor
54 6.9 3.1 4.9 1.5 versicolor
55 5.5 2.3 4 1.3 versicolor
56 6.5 2.8 4.6 1.5 versicolor
57 5.7 2.8 4.5 1.3 versicolor
58 6.3 3.3 4.7 1.6 versicolor
59 4.9 2.4 3.3 1 versicolor
60 6.6 2.9 4.6 1.3 versicolor
61 5.2 2.7 3.9 1.4 versicolor
62 5 2 3.5 1 versicolor
63 5.9 3 4.2 1.5 versicolor
64 6 2.2 4 1 versicolor
65 6.1 2.9 4.7 1.4 versicolor
66 5.6 2.9 3.6 1.3 versicolor
67 6.7 3.1 4.4 1.4 versicolor
68 5.6 3 4.5 1.5 versicolor
69 5.8 2.7 4.1 1 versicolor
70 6.2 2.2 4.5 1.5 versicolor
71 5.6 2.5 3.9 1.1 versicolor
72 5.9 3.2 4.8 1.8 versicolor
73 6.1 2.8 4 1.3 versicolor
74 6.3 2.5 4.9 1.5 versicolor
75 6.1 2.8 4.7 1.2 versicolor
76 6.4 2.9 4.3 1.3 versicolor
77 6.6 3 4.4 1.4 versicolor
78 6.8 2.8 4.8 1.4 versicolor
79 6.7 3 5 1.7 versicolor
80 6 2.9 4.5 1.5 versicolor
81 5.7 2.6 3.5 1 versicolor
82 5.5 2.4 3.8 1.1 versicolor
83 5.5 2.4 3.7 1 versicolor
84 5.8 2.7 3.9 1.2 versicolor
85 6 2.7 5.1 1.6 versicolor
86 5.4 3 4.5 1.5 versicolor
87 6 3.4 4.5 1.6 versicolor
88 6.7 3.1 4.7 1.5 versicolor
89 6.3 2.3 4.4 1.3 versicolor
90 5.6 3 4.1 1.3 versicolor
91 5.5 2.5 4 1.3 versicolor
92 5.5 2.6 4.4 1.2 versicolor
93 6.1 3 4.6 1.4 versicolor
94 5.8 2.6 4 1.2 versicolor
95 5 2.3 3.3 1 versicolor
96 5.6 2.7 4.2 1.3 versicolor
97 5.7 3 4.2 1.2 versicolor
98 5.7 2.9 4.2 1.3 versicolor
99 6.2 2.9 4.3 1.3 versicolor
100 5.1 2.5 3 1.1 versicolor
101 5.7 2.8 4.1 1.3 versicolor
102 6.3 3.3 6 2.5 virginica
103 5.8 2.7 5.1 1.9 virginica
104 7.1 3 5.9 2.1 virginica
105 6.3 2.9 5.6 1.8 virginica
106 6.5 3 5.8 2.2 virginica
107 7.6 3 6.6 2.1 virginica
108 4.9 2.5 4.5 1.7 virginica
109 7.3 2.9 6.3 1.8 virginica
110 6.7 2.5 5.8 1.8 virginica
111 7.2 3.6 6.1 2.5 virginica
112 6.5 3.2 5.1 2 virginica
113 6.4 2.7 5.3 1.9 virginica
114 6.8 3 5.5 2.1 virginica
115 5.7 2.5 5 2 virginica
116 5.8 2.8 5.1 2.4 virginica
117 6.4 3.2 5.3 2.3 virginica
118 6.5 3 5.5 1.8 virginica
119 7.7 3.8 6.7 2.2 virginica
120 7.7 2.6 6.9 2.3 virginica
121 6 2.2 5 1.5 virginica
122 6.9 3.2 5.7 2.3 virginica
123 5.6 2.8 4.9 2 virginica
124 7.7 2.8 6.7 2 virginica
125 6.3 2.7 4.9 1.8 virginica
126 6.7 3.3 5.7 2.1 virginica
127 7.2 3.2 6 1.8 virginica
128 6.2 2.8 4.8 1.8 virginica
129 6.1 3 4.9 1.8 virginica
130 6.4 2.8 5.6 2.1 virginica
131 7.2 3 5.8 1.6 virginica
132 7.4 2.8 6.1 1.9 virginica
133 7.9 3.8 6.4 2 virginica
134 6.4 2.8 5.6 2.2 virginica
135 6.3 2.8 5.1 1.5 virginica
136 6.1 2.6 5.6 1.4 virginica
137 7.7 3 6.1 2.3 virginica
138 6.3 3.4 5.6 2.4 virginica
139 6.4 3.1 5.5 1.8 virginica
140 6 3 4.8 1.8 virginica
141 6.9 3.1 5.4 2.1 virginica
142 6.7 3.1 5.6 2.4 virginica
143 6.9 3.1 5.1 2.3 virginica
144 5.8 2.7 5.1 1.9 virginica
145 6.8 3.2 5.9 2.3 virginica
146 6.7 3.3 5.7 2.5 virginica
147 6.7 3 5.2 2.3 virginica
148 6.3 2.5 5 1.9 virginica
149 6.5 3 5.2 2 virginica
150 6.2 3.4 5.4 2.3 virginica
151 5.9 3 5.1 1.8 virginica

BIN
content/data/matplotlib.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

86
content/javascript.ipynb Normal file
View File

@ -0,0 +1,86 @@
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "javascript"
},
"file_extension": ".js",
"mimetype": "text/javascript",
"name": "javascript",
"nbconvert_exporter": "javascript",
"pygments_lexer": "javascript",
"version": "es2017"
},
"kernelspec": {
"name": "javascript",
"display_name": "JavaScript",
"language": "javascript"
},
"toc-showcode": true
},
"nbformat_minor": 4,
"nbformat": 4,
"cells": [
{
"cell_type": "markdown",
"source": "# JavaScript in `JupyterLite`\n\n![](https://jupyterlite.readthedocs.io/en/latest/_static/kernelspecs/javascript.svg)",
"metadata": {}
},
{
"cell_type": "markdown",
"source": "## Standard streams",
"metadata": {}
},
{
"cell_type": "code",
"source": "console.log('hello world')",
"metadata": {
"trusted": true
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": "console.error('error')",
"metadata": {
"trusted": true
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": "## JavaScript specific constructs",
"metadata": {}
},
{
"cell_type": "code",
"source": "const delay = 2000;\n\nsetTimeout(() => {\n console.log('done');\n}, delay);",
"metadata": {
"trusted": true
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": "var str = \"hello world\"\nstr.split('').forEach(c => {\n console.log(c)\n})",
"metadata": {
"trusted": true
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": "## Markdown cells",
"metadata": {}
},
{
"cell_type": "markdown",
"source": "Lorenz system of differential equations\n\n$$\n\\begin{aligned}\n\\dot{x} & = \\sigma(y-x) \\\\\n\\dot{y} & = \\rho x - y - xz \\\\\n\\dot{z} & = -\\beta z + xy\n\\end{aligned}\n$$\n",
"metadata": {}
}
]
}

150
content/p5.ipynb Normal file
View File

@ -0,0 +1,150 @@
{
"metadata":{
"kernelspec":{
"name":"p5js",
"display_name":"p5.js",
"language":"javascript"
},
"language_info":{
"codemirror_mode":{
"name":"javascript"
},
"file_extension":".js",
"mimetype":"text/javascript",
"name":"p5js",
"nbconvert_exporter":"javascript",
"pygments_lexer":"javascript",
"version":"es2017"
}
},
"nbformat_minor":4,
"nbformat":4,
"cells":[
{
"cell_type":"markdown",
"source":"# p5 notebook\n\nA minimal Jupyter notebook UI for [p5.js](https://p5js.org) kernels.",
"metadata":{
}
},
{
"cell_type":"markdown",
"source":"First let's define a couple of variables:",
"metadata":{
}
},
{
"cell_type":"code",
"source":"var n = 4;\nvar speed = 1;",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
]
},
{
"cell_type":"markdown",
"source":"## The `setup` function\n\nThe usual p5 setup function, which creates the canvas.",
"metadata":{
}
},
{
"cell_type":"code",
"source":"function setup () {\n createCanvas(innerWidth, innerHeight);\n rectMode(CENTER);\n}",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
]
},
{
"cell_type":"markdown",
"source":"## The `draw` function\n\nFrom the [p5.js documentation](https://p5js.org/reference/#/p5/draw):\n\n> The `draw()` function continuously executes the lines of code contained inside its block until the program is stopped or `noLoop()` is called.",
"metadata":{
}
},
{
"cell_type":"code",
"source":"function draw() {\n background('#ddd');\n translate(innerWidth / 2, innerHeight / 2);\n for (let i = 0; i < n; i++) {\n push();\n rotate(frameCount * speed / 1000 * (i + 1));\n fill(i * 5, i * 100, i * 150);\n const s = 200 - i * 10;\n rect(0, 0, s, s);\n pop();\n }\n}",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
]
},
{
"cell_type":"markdown",
"source":"## Show the sketch\n\nNow let's show the sketch by using the `%show` magic:",
"metadata":{
}
},
{
"cell_type":"code",
"source":"%show",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
]
},
{
"cell_type":"markdown",
"source":"## Tweak the values\n\nWe can also tweak some values in real time:",
"metadata":{
}
},
{
"cell_type":"code",
"source":"speed = 3",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
]
},
{
"cell_type":"code",
"source":"n = 20",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
]
},
{
"cell_type":"markdown",
"source":"We can also show the sketch a second time taking into account the new values:",
"metadata":{
}
},
{
"cell_type":"code",
"source":"%show",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
]
}
]
}

View File

@ -0,0 +1,231 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Altair in `JupyterLite`\n",
"\n",
"**Altair** is a declarative statistical visualization library for Python.\n",
"\n",
"Most of the examples below are from: https://altair-viz.github.io/gallery"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Import the dependencies:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%pip install -q altair"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simple Bar Chart"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import altair as alt\n",
"import pandas as pd\n",
"\n",
"source = pd.DataFrame({\n",
" 'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],\n",
" 'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]\n",
"})\n",
"\n",
"alt.Chart(source).mark_bar().encode(\n",
" x='a',\n",
" y='b'\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simple Heatmap"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import altair as alt\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"# Compute x^2 + y^2 across a 2D grid\n",
"x, y = np.meshgrid(range(-5, 5), range(-5, 5))\n",
"z = x ** 2 + y ** 2\n",
"\n",
"# Convert this grid to columnar data expected by Altair\n",
"source = pd.DataFrame({'x': x.ravel(),\n",
" 'y': y.ravel(),\n",
" 'z': z.ravel()})\n",
"\n",
"alt.Chart(source).mark_rect().encode(\n",
" x='x:O',\n",
" y='y:O',\n",
" color='z:Q'\n",
")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install the Vega Dataset"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%pip install -q vega_datasets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Interactive Average"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import altair as alt\n",
"from vega_datasets import data\n",
"\n",
"source = data.seattle_weather()\n",
"brush = alt.selection(type='interval', encodings=['x'])\n",
"\n",
"bars = alt.Chart().mark_bar().encode(\n",
" x='month(date):O',\n",
" y='mean(precipitation):Q',\n",
" opacity=alt.condition(brush, alt.OpacityValue(1), alt.OpacityValue(0.7)),\n",
").add_selection(\n",
" brush\n",
")\n",
"\n",
"line = alt.Chart().mark_rule(color='firebrick').encode(\n",
" y='mean(precipitation):Q',\n",
" size=alt.SizeValue(3)\n",
").transform_filter(\n",
" brush\n",
")\n",
"\n",
"alt.layer(bars, line, data=source)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Locations of US Airports"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import altair as alt\n",
"from vega_datasets import data\n",
"\n",
"airports = data.airports.url\n",
"states = alt.topo_feature(data.us_10m.url, feature='states')\n",
"\n",
"# US states background\n",
"background = alt.Chart(states).mark_geoshape(\n",
" fill='lightgray',\n",
" stroke='white'\n",
").properties(\n",
" width=500,\n",
" height=300\n",
").project('albersUsa')\n",
"\n",
"# airport positions on background\n",
"points = alt.Chart(airports).transform_aggregate(\n",
" latitude='mean(latitude)',\n",
" longitude='mean(longitude)',\n",
" count='count()',\n",
" groupby=['state']\n",
").mark_circle().encode(\n",
" longitude='longitude:Q',\n",
" latitude='latitude:Q',\n",
" size=alt.Size('count:Q', title='Number of Airports'),\n",
" color=alt.value('steelblue'),\n",
" tooltip=['state:N','count:Q']\n",
").properties(\n",
" title='Number of airports in US'\n",
")\n",
"\n",
"background + points\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (Pyodide)",
"language": "python",
"name": "python"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,154 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"# `folium` Interactive Map Demo\n",
"\n",
"Simple demonstration of rendering a map in a `jupyterlite` notebook.\n",
"\n",
"Note that the `folium` package has several dependencies which themselves may have dependencies.\n",
"\n",
"The following code fragement, run in a fresh Python enviroment into which `folium` has already been installed, identifies the packages that are loaded in when `folium` is loaded:\n",
"\n",
"```python\n",
"#https://stackoverflow.com/a/40381601/454773\n",
"import sys\n",
"before = [str(m) for m in sys.modules]\n",
"import folium\n",
"after = [str(m) for m in sys.modules]\n",
"set([m.split('.')[0] for m in after if not m in before and not m.startswith('_')])\n",
"```\n",
"\n",
"The loaded packages are:\n",
"\n",
"```\n",
"{'branca',\n",
" 'certifi',\n",
" 'chardet',\n",
" 'cmath',\n",
" 'csv',\n",
" 'dateutil',\n",
" 'encodings',\n",
" 'folium',\n",
" 'gzip',\n",
" 'http',\n",
" 'idna',\n",
" 'importlib',\n",
" 'jinja2',\n",
" 'markupsafe',\n",
" 'mmap',\n",
" 'numpy',\n",
" 'pandas',\n",
" 'pkg_resources',\n",
" 'pytz',\n",
" 'requests',\n",
" 'secrets',\n",
" 'stringprep',\n",
" 'urllib3',\n",
" 'zipfile'}\n",
" ```\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following packages seem to need installing in order load `folium`, along with folium itself:\n",
"\n",
"```\n",
"chardet, certifi, idna, branca, urllib3, Jinja2, requests, Markupsafe\n",
"```\n",
"\n",
"Universal wheels, with filenames of the form `PACKAGE-VERSION-py2.py3-none-any.whl` appearing in the *Download files* area of a PyPi package page ([example](https://pypi.org/project/requests/#files)] are required in order to install the package.\n",
"\n",
"One required package, [`Markupsafe`](https://pypi.org/project/Markupsafe/#files)) *did not* have a universal wheel available, so a wheel was manually built elsewhere (by hacking the [`setup.py` file](https://github.com/pallets/markupsafe/blob/main/setup.py) to force it to build the wheel in a platform and speedup free way) and pushed to a downloadable location in an [*ad hoc* wheelhouse](https://opencomputinglab.github.io/vce-wheelhouse/)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"# Install folium requirements\n",
"%pip install -q folium"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Demo of `folium` Map\n",
"\n",
"Load in the `folium` package:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import folium"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And render a demo map:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"m = folium.Map(location=[50.693848, -1.304734], zoom_start=11)\n",
"m"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (Pyodide)",
"language": "python",
"name": "python"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
},
"orig_nbformat": 4,
"toc-showcode": false
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,268 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9ca234f7-84b7-4107-9bcd-74f5a4ffd07d",
"metadata": {},
"source": [
"# `ipywidgets` Interactive Demo\n",
"\n",
"Simple demonstration of rendering Interactive widgets in a `jupyterlite` notebook.\n",
"\n",
"`ipywidgets` can be installed in this deployment (it provides the @jupyter-widgets/jupyterlab-manager federated extension), but you will need to make your own deployment to have access to other interactive widgets libraries."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d62fba6e",
"metadata": {},
"outputs": [],
"source": [
"%pip install -q ipywidgets"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3bab23f8-de91-43c9-9cec-84f4924425fc",
"metadata": {},
"outputs": [],
"source": [
"from ipywidgets import IntSlider"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a15c5acb-ee72-4005-8761-5693db853f22",
"metadata": {},
"outputs": [],
"source": [
"slider = IntSlider()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8ba89682-e0d7-4bd2-961a-f9956850fd5a",
"metadata": {},
"outputs": [],
"source": [
"slider"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "50510ade-668f-4477-8cb2-41574609ac73",
"metadata": {},
"outputs": [],
"source": [
"slider"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7bac1ed8-8c77-426b-a781-1c1a6cfad829",
"metadata": {},
"outputs": [],
"source": [
"slider.value"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "976a70a0-e99d-4c20-b005-f59bbba10f85",
"metadata": {},
"outputs": [],
"source": [
"slider.value = 5"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3134c76e-cffb-4701-8230-e6c4bfbbfdb9",
"metadata": {},
"outputs": [],
"source": [
"from ipywidgets import IntText, link"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f7b3fe0a-5695-4ef2-a573-40785e68fbae",
"metadata": {},
"outputs": [],
"source": [
"text = IntText()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5e2fd50e-19e0-4e20-a1f7-ad65400ec636",
"metadata": {},
"outputs": [],
"source": [
"text"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bb3bedce-7311-48c0-aeab-8fe3aa554b92",
"metadata": {},
"outputs": [],
"source": [
"link((slider, 'value'), (text, 'value'));"
]
},
{
"cell_type": "markdown",
"id": "71b68c3e-184e-4320-9513-d0bc72800a85",
"metadata": {},
"source": [
"# `bqplot` Interactive Demo\n",
"\n",
"Plotting in JupyterLite\n",
"\n",
"`bqplot` can be installed in this deployment (it provides the bqplot federated extension), but you will need to make your own deployment to have access to other interactive widgets libraries."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "119eb9a3-ac98-42c3-98d4-1ac460eb75d3",
"metadata": {},
"outputs": [],
"source": [
"%pip install -q bqplot"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "23b32857-2958-4083-b16a-ac26cd2408d4",
"metadata": {},
"outputs": [],
"source": [
"from bqplot import *\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"np.random.seed(0)\n",
"\n",
"n = 100\n",
"\n",
"x = list(range(n))\n",
"y = np.cumsum(np.random.randn(n)) + 100.\n",
"\n",
"sc_x = LinearScale()\n",
"sc_y = LinearScale()\n",
"\n",
"lines = Lines(\n",
" x=x, y=y,\n",
" scales={'x': sc_x, 'y': sc_y}\n",
")\n",
"ax_x = Axis(scale=sc_x, label='Index')\n",
"ax_y = Axis(scale=sc_y, orientation='vertical', label='lines')\n",
"\n",
"Figure(marks=[lines], axes=[ax_x, ax_y], title='Lines')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ddb6b44e-06a0-4049-a79d-33ffc90d5a03",
"metadata": {},
"outputs": [],
"source": [
"lines.colors = ['green']"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e367e7fb-b403-41aa-9629-224827ec3005",
"metadata": {},
"outputs": [],
"source": [
"lines.fill = 'bottom'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d4a167f3-07c4-4880-92f5-7fcdea0c61c6",
"metadata": {},
"outputs": [],
"source": [
"lines.marker = 'circle'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1d1342f7-ec08-4f53-84dc-d712226d9e46",
"metadata": {},
"outputs": [],
"source": [
"n = 100\n",
"\n",
"x = list(range(n))\n",
"y = np.cumsum(np.random.randn(n))\n",
"\n",
"sc_x = LinearScale()\n",
"sc_y = LinearScale()\n",
"\n",
"bars = Bars(\n",
" x=x, y=y,\n",
" scales={'x': sc_x, 'y': sc_y}\n",
")\n",
"ax_x = Axis(scale=sc_x, label='Index')\n",
"ax_y = Axis(scale=sc_y, orientation='vertical', label='bars')\n",
"\n",
"Figure(marks=[bars], axes=[ax_x, ax_y], title='Bars', animation_duration=1000)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f86bbcfb-5b02-4700-b8d6-f90068893b55",
"metadata": {},
"outputs": [],
"source": [
"bars.y = np.cumsum(np.random.randn(n))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (Pyodide)",
"language": "python",
"name": "python"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
},
"orig_nbformat": 4,
"toc-showcode": false
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,178 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ipycanvas: John Conway's Game Of Life"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some of the following code is adapted from https://jakevdp.github.io/blog/2013/08/07/conways-game-of-life/"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%pip install -q ipycanvas"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import asyncio\n",
"\n",
"import numpy as np\n",
"\n",
"from ipycanvas import RoughCanvas, hold_canvas"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"def life_step(x):\n",
" \"\"\"Game of life step\"\"\"\n",
" nbrs_count = sum(np.roll(np.roll(x, i, 0), j, 1)\n",
" for i in (-1, 0, 1) for j in (-1, 0, 1)\n",
" if (i != 0 or j != 0))\n",
" return (nbrs_count == 3) | (x & (nbrs_count == 2))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"def draw(x, canvas, color='black'):\n",
" with hold_canvas(canvas):\n",
" canvas.clear()\n",
" canvas.fill_style = '#FFF0C9'\n",
" canvas.rough_fill_style = 'solid'\n",
" canvas.fill_rect(-10, -10, canvas.width + 10, canvas.height + 10)\n",
" canvas.rough_fill_style = 'cross-hatch'\n",
"\n",
" canvas.fill_style = color\n",
" canvas.stroke_style = color\n",
"\n",
" living_cells = np.where(x)\n",
" \n",
" rects_x = living_cells[1] * n_pixels\n",
" rects_y = living_cells[0] * n_pixels\n",
"\n",
" canvas.fill_rects(rects_x, rects_y, n_pixels)\n",
" canvas.stroke_rects(rects_x, rects_y, n_pixels)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"glider_gun =\\\n",
"[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],\n",
" [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0],\n",
" [0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1],\n",
" [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1],\n",
" [1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\n",
" [1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0],\n",
" [0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],\n",
" [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\n",
" [0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]\n",
"\n",
"x = np.zeros((50, 70), dtype=bool)\n",
"x[1:10,1:37] = glider_gun"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"n_pixels = 15\n",
"\n",
"canvas = RoughCanvas(width=x.shape[1]*n_pixels, height=x.shape[0]*n_pixels)\n",
"canvas.fill_style = '#FFF0C9'\n",
"canvas.rough_fill_style = 'solid'\n",
"canvas.fill_rect(0, 0, canvas.width, canvas.height)\n",
"\n",
"canvas"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"draw(x, canvas, '#5770B3')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"for _ in range(300):\n",
" x = life_step(x)\n",
" draw(x, canvas, '#5770B3')\n",
"\n",
" await asyncio.sleep(0.1)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (Pyodide)",
"language": "python",
"name": "python"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
},
"orig_nbformat": 4,
"toc-showcode": false
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,259 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install -q bqplot ipyleaflet"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from urllib.request import urlopen\n",
"import json\n",
"from datetime import datetime\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"from js import fetch\n",
"\n",
"from ipywidgets import Dropdown\n",
"\n",
"from bqplot import Lines, Figure, LinearScale, DateScale, Axis\n",
"\n",
"from ipyleaflet import Map, GeoJSON, WidgetControl"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"URL = \"https://raw.githubusercontent.com/jupyter-widgets/ipyleaflet/master/examples/nations.json\"\n",
"\n",
"res = await fetch(URL)\n",
"text = await res.text()\n",
"\n",
"data = pd.read_json(text)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def clean_data(data):\n",
" for column in ['income', 'lifeExpectancy', 'population']:\n",
" data = data.drop(data[data[column].apply(len) <= 4].index)\n",
" return data\n",
"\n",
"def extrap_interp(data):\n",
" data = np.array(data)\n",
" x_range = np.arange(1800, 2009, 1.)\n",
" y_range = np.interp(x_range, data[:, 0], data[:, 1])\n",
" return y_range\n",
"\n",
"def extrap_data(data):\n",
" for column in ['income', 'lifeExpectancy', 'population']:\n",
" data[column] = data[column].apply(extrap_interp)\n",
" return data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"data = clean_data(data)\n",
"data = extrap_data(data)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"date_start = datetime(1800, 12, 31)\n",
"date_end = datetime(2009, 12, 31)\n",
"\n",
"date_scale = DateScale(min=date_start, max=date_end)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"date_data = pd.date_range(start=date_start, end=date_end, freq='A', normalize=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"country_name = 'Angola'\n",
"data_name = 'income'\n",
"\n",
"x_data = data[data.name == country_name][data_name].values[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x_scale = LinearScale()\n",
"\n",
"lines = Lines(x=date_data, y=x_data, scales={'x': date_scale, 'y': x_scale})\n",
"\n",
"ax_x = Axis(label='Year', scale=date_scale, num_ticks=10, tick_format='%Y')\n",
"ax_y = Axis(label=data_name.capitalize(), scale=x_scale, orientation='vertical', side='left')\n",
"\n",
"figure = Figure(axes=[ax_x, ax_y], title=country_name, marks=[lines], animation_duration=500,\n",
" layout={'max_height': '250px', 'max_width': '400px'})"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def update_figure(country_name, data_name):\n",
" try:\n",
" lines.y = data[data.name == country_name][data_name].values[0]\n",
" ax_y.label = data_name.capitalize()\n",
" figure.title = country_name\n",
" except IndexError:\n",
" pass"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"URL = \"https://raw.githubusercontent.com/jupyter-widgets/ipyleaflet/master/examples/countries.geo.json\"\n",
"\n",
"res = await fetch(URL)\n",
"text = await res.text()\n",
"\n",
"countries = json.loads(text)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m = Map(zoom=3)\n",
"\n",
"geo = GeoJSON(data=countries, style={'fillColor': 'white', 'weight': 0.5}, hover_style={'fillColor': '#1f77b4'}, name='Countries')\n",
"m.add_layer(geo)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"widget_control1 = WidgetControl(widget=figure, position='bottomright')\n",
"\n",
"m.add_control(widget_control1)\n",
"\n",
"def on_hover(event, feature, **kwargs):\n",
" global country_name\n",
"\n",
" country_name = feature['properties']['name']\n",
" update_figure(country_name, data_name)\n",
"\n",
"geo.on_hover(on_hover)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dropdown = Dropdown(\n",
" options=['income', 'population', 'lifeExpectancy'],\n",
" value=data_name,\n",
" description='Plotting:'\n",
")\n",
"\n",
"def on_click(change):\n",
" global data_name\n",
"\n",
" data_name = change['new']\n",
" update_figure(country_name, data_name)\n",
"\n",
"dropdown.observe(on_click, 'value')\n",
"\n",
"widget_control2 = WidgetControl(widget=dropdown, position='bottomleft')\n",
"\n",
"m.add_control(widget_control2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (Pyodide)",
"language": "python",
"name": "python"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
},
"orig_nbformat": 4,
"toc-showcode": false
},
"nbformat": 4,
"nbformat_minor": 4
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,158 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Plotly in JupyterLite\n",
"\n",
"`plotly.py` is an interactive, open-source, and browser-based graphing library for Python: https://plotly.com/python/"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install -q nbformat plotly"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"## Basic Figure"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import plotly.graph_objects as go\n",
"fig = go.Figure()\n",
"fig.add_trace(go.Scatter(y=[2, 1, 4, 3]))\n",
"fig.add_trace(go.Bar(y=[1, 4, 3, 2]))\n",
"fig.update_layout(title = 'Hello Figure')\n",
"fig.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"## Basic Table with a Pandas DataFrame"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import plotly.graph_objects as go\n",
"import pandas as pd\n",
"\n",
"from js import fetch\n",
"\n",
"URL = \"https://raw.githubusercontent.com/plotly/datasets/master/2014_usa_states.csv\"\n",
"\n",
"res = await fetch(URL)\n",
"text = await res.text()\n",
"\n",
"filename = 'data.csv'\n",
"\n",
"with open(filename, 'w') as f:\n",
" f.write(text)\n",
"\n",
"df = pd.read_csv(filename)\n",
"\n",
"fig = go.Figure(data=[go.Table(\n",
" header=dict(values=list(df.columns),\n",
" fill_color='paleturquoise',\n",
" align='left'),\n",
" cells=dict(values=[df.Rank, df.State, df.Postal, df.Population],\n",
" fill_color='lavender',\n",
" align='left'))\n",
"])\n",
"\n",
"fig.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quiver Plot with Points"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import plotly.figure_factory as ff\n",
"import plotly.graph_objects as go\n",
"\n",
"import numpy as np\n",
"\n",
"x,y = np.meshgrid(np.arange(-2, 2, .2),\n",
" np.arange(-2, 2, .25))\n",
"z = x*np.exp(-x**2 - y**2)\n",
"v, u = np.gradient(z, .2, .2)\n",
"\n",
"# Create quiver figure\n",
"fig = ff.create_quiver(x, y, u, v,\n",
" scale=.25,\n",
" arrow_scale=.4,\n",
" name='quiver',\n",
" line_width=1)\n",
"\n",
"# Add points to figure\n",
"fig.add_trace(go.Scatter(x=[-.7, .75], y=[0,0],\n",
" mode='markers',\n",
" marker_size=12,\n",
" name='points'))\n",
"\n",
"fig.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (Pyodide)",
"language": "python",
"name": "python"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
},
"orig_nbformat": 4,
"toc-showcode": false
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,649 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "b07a3b47-2262-4135-a1d2-52e8392b44eb",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.2')\n"
]
},
{
"cell_type": "markdown",
"id": "49c3f9ea-23ce-4c5c-b3fe-44f1cecadf20",
"metadata": {},
"source": [
"pyb2d is imported as b2d"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dff93359-2c68-467a-9239-478a0e550a4b",
"metadata": {},
"outputs": [],
"source": [
"import b2d\n",
"# import pyb2d_jupyterlite_backend\n",
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"import numpy as np\n",
"import matplotlib.pylab as plt"
]
},
{
"cell_type": "markdown",
"id": "bc977c4e-75ee-4349-9408-650c3dcd01e0",
"metadata": {},
"source": [
"# Tutorial 0: A free falling body\n",
"The first step with Box2D is the creation of the world. The world is parametrized by a gravity vector."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4ff914a6-eb18-45a1-b1ed-e8ad7ab0d298",
"metadata": {},
"outputs": [],
"source": [
"# the world\n",
"gravity = (0, -10)\n",
"world = b2d.World(gravity)"
]
},
{
"cell_type": "markdown",
"id": "3afdbb2a-e694-4779-b95e-73a5b38d34b6",
"metadata": {},
"source": [
"Create a circle-shaped body"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "99837a63-4628-483c-8f2d-cc4aec9cb1d5",
"metadata": {},
"outputs": [],
"source": [
"# the body def\n",
"body_def = b2d.BodyDef()\n",
"body_def.type = b2d.BodyType.dynamic\n",
"body_def.position = (0, 0)\n",
"\n",
"# the body\n",
"body = world.create_body(body_def)\n",
"\n",
"# shape\n",
"circle_shape = b2d.CircleShape()\n",
"circle_shape.radius = 1.0\n",
"\n",
"# the fixture\n",
"fixture_def = b2d.FixtureDef()\n",
"fixture_def.shape = circle_shape\n",
"fixture_def.density = 1.0\n",
"\n",
"# create and add the fixture to the body\n",
"fixture = body.create_fixture(fixture_def)"
]
},
{
"cell_type": "markdown",
"id": "bf9758a6-fb6e-4f9c-b15f-783f9488cf7e",
"metadata": {},
"source": [
"We can now have a look at the world: We render the world st. each meter in the Box2D world will be 100 pixels in the image:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8b433892-3c82-43be-a085-eda3e4279b2c",
"metadata": {},
"outputs": [],
"source": [
"# from b2d.plot import render_world\n",
"b2d.plot.plot_world(world, ppm=100)"
]
},
{
"cell_type": "markdown",
"id": "5e1db1f1-6e47-454c-9ea9-86262d7da309",
"metadata": {},
"source": [
"Lets run the world for a total of 5 seconds. \n",
"Usually one wants to run the world at a certain frame rate.\n",
"With the frame rate and the total time we can compute the delta for each iteration and how many steps we need"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "41a232a9-a3c5-425d-9aed-d3adb90d6314",
"metadata": {},
"outputs": [],
"source": [
"t = 5\n",
"fps = 40\n",
"dt = 1.0 / fps\n",
"n_steps = int(t / dt + 0.5)\n",
"print(f\"t={t} fps={fps} dt={dt} n_steps={n_steps}\")"
]
},
{
"cell_type": "markdown",
"id": "4d458acb-6d5c-47ba-bcbf-d15ea2cf2537",
"metadata": {},
"source": [
"in each step we query the bodies position and velocity and store then for later plotting"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4e042c7b-07a7-445f-ba04-e38173b46c0f",
"metadata": {},
"outputs": [],
"source": [
"positions = np.zeros([n_steps, 2])\n",
"velocites = np.zeros([n_steps, 2])\n",
"timepoints = np.zeros([n_steps])\n",
"\n",
"t_elapsed = 0.0\n",
"for i in range(n_steps):\n",
"\n",
" # get the bodies center of mass\n",
" positions[i, :] = body.world_center\n",
"\n",
" # get the bodies velocity\n",
" velocites[i, :] = body.linear_velocity\n",
"\n",
" timepoints[i] = t_elapsed\n",
"\n",
" world.step(time_step=dt, velocity_iterations=1, position_iterations=1)\n",
" t_elapsed += dt"
]
},
{
"cell_type": "markdown",
"id": "0ec7d66c-c979-40fa-8af3-9e99873ec105",
"metadata": {},
"source": [
"plot the y-position against the time. We can see that the body is falling down in an accelerating way:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "434cb907-1b76-414e-bb5e-6ea32dd1f829",
"metadata": {},
"outputs": [],
"source": [
"plt.plot(timepoints, positions[:, 1])\n",
"plt.ylabel('y-poistion [meter]')\n",
"plt.xlabel('t [sec]')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "b7f58954-4ea1-49f9-b0b0-7df38336860d",
"metadata": {},
"source": [
"as expected the x position is not changing since the gravity vector is non-zero only in the x direction"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "39573eed-e6c8-45bf-8e35-4251b660ce3f",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"plt.plot(timepoints, positions[:, 0])\n",
"plt.ylabel('x-poistion [meter]')\n",
"plt.xlabel('t [sec]')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "cdb98dc5-3bc8-4933-91a0-a1db3afb9c34",
"metadata": {},
"source": [
"# Tutorial 1: A falling body in a box, more pythonic\n",
"Create a world, but in a more pythonic way, and animate the world"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d58c2639-21da-490b-8dcd-205962f63dfc",
"metadata": {},
"outputs": [],
"source": [
"# the world\n",
"world = b2d.world(gravity=(0, -10))\n",
"\n",
"# create the dynamic body\n",
"body = world.create_dynamic_body(\n",
" position=(5, 5),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=1), density=1, restitution=0.75),\n",
")\n",
"\n",
"# create a box\n",
"box_shape = b2d.ChainShape()\n",
"box_shape.create_loop([(0, 0), (0, 10),(10,10),(10, 0)])\n",
"box = world.create_static_body(\n",
" position=(0, 0), fixtures=b2d.fixture_def(shape=box_shape, friction=0)\n",
")\n",
"b2d.plot.animate_world(world, ppm=20, t=10)"
]
},
{
"cell_type": "markdown",
"id": "10dbb85a-84b0-4820-8fb3-6108d9c0fe00",
"metadata": {},
"source": [
"note that when we animate that world again, the body has already been fallen"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c919702c-7c62-4d87-bf1f-df5027d72a83",
"metadata": {},
"outputs": [],
"source": [
"b2d.plot.animate_world(world, ppm=20, t=2)"
]
},
{
"cell_type": "markdown",
"id": "7322e9c5-8608-4375-81ed-766cbb2af927",
"metadata": {},
"source": [
"# Tutorial 2: Interactive worlds\n",
"While animating the world already is already nice, interacting with the world is even better.\n",
"pyb2d has a framwork to interact with the world for multiple backends.\n",
"This framework is called `TestbedBase` since you can \"test\" your world in an interactive way"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "97cddd47-5a88-4cae-8543-cfcdf658255a",
"metadata": {},
"outputs": [],
"source": [
"from b2d.testbed import TestbedBase\n",
"\n",
"class InteractiveExample(TestbedBase):\n",
" def __init__(self, settings=None):\n",
" super(InteractiveExample, self).__init__(settings=settings)\n",
" # create two balls\n",
" body = self.world.create_dynamic_body(position=(5, 5),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=1), density=1, restitution=0.5),\n",
" )\n",
" body = self.world.create_dynamic_body(position=(8, 5),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=1), density=1, restitution=0.8),\n",
" )\n",
" # create a box\n",
" box_shape = b2d.ChainShape()\n",
" box_shape.create_loop([(0, 0), (0, 10),(10,10),(10, 0)])\n",
" box = self.world.create_static_body(\n",
" position=(0, 0), fixtures=b2d.fixture_def(shape=box_shape, friction=0)\n",
" )\n",
" \n",
"s = JupyterAsyncGui.Settings()\n",
"s.resolution = [300,300]\n",
"b2d.testbed.run(InteractiveExample, backend=JupyterAsyncGui, gui_settings=s);"
]
},
{
"cell_type": "markdown",
"id": "64bf55d1-4117-4af0-8f1f-65de33751743",
"metadata": {
"tags": []
},
"source": [
"# Tutorial 3: Joints"
]
},
{
"cell_type": "markdown",
"id": "07147cab-23be-4406-85f7-4b3d174e3954",
"metadata": {
"tags": []
},
"source": [
"## Tutorial 3.1: Prismatic Joint"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9a2d178d-33d7-4c51-b0ff-f66c98cac673",
"metadata": {},
"outputs": [],
"source": [
"world = b2d.world(gravity=(0, -10))\n",
"anchor_body = world.create_static_body(position=(0, 0))\n",
"b = world.create_dynamic_body(\n",
" position=(10, 10),\n",
" fixtures=b2d.fixture_def(shape=b2d.polygon_shape(box=[2, 0.5]), density=1),\n",
" linear_damping=0.0,\n",
" angular_damping=0.0,\n",
")\n",
"world.create_prismatic_joint(anchor_body, b, local_axis_a=(1, 1))\n",
"b2d.plot.animate_world(world, ppm=20, t=3, bounding_box=((0,0),(10,10)))"
]
},
{
"cell_type": "markdown",
"id": "07971d69-b2ef-4d74-8c1c-48f38dcc708c",
"metadata": {
"tags": []
},
"source": [
"## Tutorial 3.2: Pully Joint"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "39b7fef2-4b4b-4904-9899-1a34f1039693",
"metadata": {},
"outputs": [],
"source": [
"world = b2d.world(gravity=(0, -10))\n",
"\n",
"\n",
"a = world.create_dynamic_body(\n",
" position=(-5, 0),\n",
" fixtures=b2d.fixture_def(shape=b2d.polygon_shape(box=[2, 0.8]), density=1),\n",
" linear_damping=0.0,\n",
" angular_damping=0.0,\n",
")\n",
"b = world.create_dynamic_body(\n",
" position=(5, 0),\n",
" fixtures=b2d.fixture_def(shape=b2d.polygon_shape(box=[2, 0.5]), density=1),\n",
" linear_damping=0.0,\n",
" angular_damping=0.0,\n",
")\n",
"world.create_pully_joint(\n",
" a,\n",
" b,\n",
" length_a=10,\n",
" length_b=10,\n",
" ground_anchor_a=(-5, 10),\n",
" ground_anchor_b=(5, 10),\n",
" local_anchor_a=(0, 0),\n",
" local_anchor_b=(0, 0),\n",
")\n",
"b2d.plot.animate_world(world, ppm=20, t=5, bounding_box=((-10,-12),(10,12)))"
]
},
{
"cell_type": "markdown",
"id": "7e8fb17d-1dda-45cb-98df-6b98be5b4e6c",
"metadata": {},
"source": [
"## Tutorial 3.3: Revolute Joint"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a2686e5f-3fa2-412d-8a40-2e9a67123d43",
"metadata": {},
"outputs": [],
"source": [
"world = b2d.world(gravity=(0, -10))\n",
"bodies = []\n",
"b = world.create_static_body(position=(0, 15))\n",
"bodies.append(b)\n",
"for i in range(5):\n",
" b = world.create_dynamic_body(\n",
" position=(i * 4 + 2, 15),\n",
" fixtures=b2d.fixture_def(shape=b2d.polygon_shape(box=[2, 0.5]), density=1),\n",
" linear_damping=0.0,\n",
" angular_damping=0.0,\n",
" )\n",
" bodies.append(b)\n",
"world.create_revolute_joint(\n",
" bodies[0], bodies[1], local_anchor_a=(0, 0), local_anchor_b=(-2, 0.0)\n",
")\n",
"for i in range(1, len(bodies) - 1):\n",
" a = bodies[i]\n",
" b = bodies[i + 1]\n",
" world.create_revolute_joint(a, b, local_anchor_a=(2, 0.0), local_anchor_b=(-2, 0.0))\n",
"b2d.plot.animate_world(world, ppm=20, t=5, bounding_box=((-20,-10),(20,20)))"
]
},
{
"cell_type": "markdown",
"id": "9caa18f0-4eb7-4e72-8445-8f6d096d9465",
"metadata": {
"tags": []
},
"source": [
"## Tutorial 3.4: Weld Joint"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3d74fb2f-7da5-4ad7-8f21-fba1f97acee2",
"metadata": {},
"outputs": [],
"source": [
"# the world\n",
"world = b2d.world(gravity=(0, -10))\n",
"\n",
"\n",
"bodies = []\n",
"\n",
"# create a static body as anchor\n",
"b = world.create_static_body(\n",
" position=(0, 4), fixtures=b2d.fixture_def(shape=b2d.polygon_shape(box=[0.3, 0.5]))\n",
")\n",
"bodies.append(b)\n",
"\n",
"for i in range(4):\n",
" b = world.create_dynamic_body(\n",
" position=(i + 1.0, 4),\n",
" fixtures=b2d.fixture_def(shape=b2d.polygon_shape(box=[0.3, 0.5]), density=0.1),\n",
" linear_damping=2.5,\n",
" angular_damping=2.5,\n",
" )\n",
" bodies.append(b)\n",
"\n",
"for i in range(len(bodies) - 1):\n",
" a = bodies[i]\n",
" b = bodies[i + 1]\n",
" world.create_weld_joint(\n",
" a,\n",
" b,\n",
" local_anchor_a=(0.5, 0.5),\n",
" local_anchor_b=(-0.5, 0.5),\n",
" damping=0.1,\n",
" reference_angle=0,\n",
" stiffness=20,\n",
" )\n",
" world.create_weld_joint(\n",
" a,\n",
" b,\n",
" local_anchor_a=(0.5, -0.5),\n",
" local_anchor_b=(-0.5, -0.5),\n",
" damping=0.1,\n",
" reference_angle=0,\n",
" stiffness=20,\n",
" )\n",
"b2d.plot.animate_world(world, ppm=20, t=5, bounding_box=((0,-5),(5,5)))"
]
},
{
"cell_type": "markdown",
"id": "7373461e-d1fa-4ad9-aeaa-048287839fd9",
"metadata": {},
"source": [
"## Tutorial 3.5: Wheel Joint"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1eb711e0-ae53-43ed-b0c1-c0a2fe42b407",
"metadata": {},
"outputs": [],
"source": [
"world = b2d.world(gravity=(0, -10))\n",
"edge = world.create_static_body(\n",
" position=(0, 0), fixtures=b2d.fixture_def(shape=b2d.edge_shape([(-20, 0), (5, 0)]))\n",
")\n",
"\n",
"# random slope\n",
"x = np.linspace(5, 50, 10)\n",
"y = np.random.rand(10) * 4 - 2\n",
"y[0] = 0\n",
"xy = np.stack([x, y]).T\n",
"xy = np.flip(xy, axis=0)\n",
"edge = world.create_static_body(\n",
" position=(0, 0),\n",
" fixtures=b2d.fixture_def(shape=b2d.chain_shape(xy, prev_vertex=(10, 0))),\n",
")\n",
"# create car\n",
"left_wheel = world.create_dynamic_body(\n",
" position=(-3, 2),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=2), density=1),\n",
")\n",
"right_wheel = world.create_dynamic_body(\n",
" position=(3, 2),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=2), density=1),\n",
")\n",
"\n",
"chasis = world.create_dynamic_body(\n",
" position=(0, 2),\n",
" fixtures=b2d.fixture_def(shape=b2d.polygon_shape(box=[3, 0.5]), density=1),\n",
")\n",
"\n",
"wheel_joint_def = dict(\n",
" stiffness=10,\n",
" enable_motor=True,\n",
" motor_speed=-100,\n",
" max_motor_torque=100,\n",
" collide_connected=False,\n",
" enable_limit=True,\n",
" lower_translation=-0.4,\n",
" upper_translation=0.4,\n",
" local_axis_a=(0, 1),\n",
")\n",
"world.create_wheel_joint(chasis, left_wheel, local_anchor_a=(-3, 0), **wheel_joint_def)\n",
"world.create_wheel_joint(chasis, right_wheel, local_anchor_a=(3, 0), **wheel_joint_def)\n",
"\n",
"\n",
"b2d.plot.animate_world(world, ppm=20, t=15, bounding_box=((-10,-5),(20,5)))"
]
},
{
"cell_type": "markdown",
"id": "d9a0fffc-ae40-47ec-b185-2a6fe0dde496",
"metadata": {},
"source": [
"## Tutorial 3.6: Distance Joint"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3c121398-f08f-4ea0-a875-de141ba53508",
"metadata": {},
"outputs": [],
"source": [
"world = b2d.world(gravity=(0, -10))\n",
"\n",
"for i in range(10):\n",
"\n",
" # create static anchor (does not need shape/fixture)\n",
" anchor = world.create_static_body(position=(i, 0))\n",
"\n",
" # 5 below the anchor\n",
" body = world.create_dynamic_body(\n",
" position=(i, -10),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=0.4), density=0.5),\n",
" )\n",
"\n",
" # distance joints of various stiffness-es\n",
" world.create_distance_joint(anchor, body, length=10, stiffness=0.5 * (i + 1))\n",
"\n",
"b2d.plot.animate_world(world, ppm=20, t=10, bounding_box=((-2,-20),(10,0)))"
]
},
{
"cell_type": "markdown",
"id": "fb6afaff-8236-4206-85c7-3ba2de466ba9",
"metadata": {},
"source": [
"# Tutorial 4: Particles"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8f5c3b83-51d9-47cb-9b73-d5f8b0e03a76",
"metadata": {},
"outputs": [],
"source": [
"world = b2d.world(gravity=(0, -10))\n",
"pdef = b2d.particle_system_def(radius=0.1)\n",
"psystem = world.create_particle_system(pdef)\n",
"\n",
"emitter_pos = (0, 0)\n",
"emitter_def = b2d.RandomizedLinearEmitterDef()\n",
"emitter_def.emite_rate = 400\n",
"emitter_def.lifetime = 5.1\n",
"emitter_def.size = (2, 1)\n",
"emitter_def.velocity = (6, 20)\n",
"emitter = b2d.RandomizedLinearEmitter(psystem, emitter_def)\n",
"b2d.plot.animate_world(world, ppm=20, t=10, bounding_box=((-10,-20),(20,5)), pre_step=emitter.step)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ea9d7882-d3a4-45bb-b59b-cb1c9cd33990",
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,123 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.2')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from b2d.testbed import TestbedBase\n",
"import random\n",
"import numpy\n",
"import b2d\n",
"\n",
"class ColorMixing(TestbedBase):\n",
"\n",
" name = \"ColorMixing\"\n",
"\n",
" def __init__(self, settings=None):\n",
" super(ColorMixing, self).__init__(settings=settings)\n",
" dimensions = [30, 30]\n",
"\n",
" # the outer box\n",
" box_shape = b2d.ChainShape()\n",
" box_shape.create_loop(\n",
" [\n",
" (0, 0),\n",
" (0, dimensions[1]),\n",
" (dimensions[0], dimensions[1]),\n",
" (dimensions[0], 0),\n",
" ]\n",
" )\n",
" box = self.world.create_static_body(position=(0, 0), shape=box_shape)\n",
"\n",
" fixtureA = b2d.fixture_def(\n",
" shape=b2d.circle_shape(1), density=2.2, friction=0.2, restitution=0.5\n",
" )\n",
" body = self.world.create_dynamic_body(position=(13, 10), fixtures=fixtureA)\n",
"\n",
" pdef = b2d.particle_system_def(\n",
" viscous_strength=0.9,\n",
" spring_strength=0.0,\n",
" damping_strength=0.5,\n",
" pressure_strength=0.5,\n",
" color_mixing_strength=0.008,\n",
" density=2,\n",
" )\n",
" psystem = self.world.create_particle_system(pdef)\n",
" psystem.radius = 0.3\n",
" psystem.damping = 1.0\n",
"\n",
" colors = [\n",
" (255, 0, 0, 255),\n",
" (0, 255, 0, 255),\n",
" (0, 0, 255, 255),\n",
" (255, 255, 0, 255),\n",
" ]\n",
" posiitons = [(6, 10), (20, 10), (20, 20), (6, 20)]\n",
" for color, pos in zip(colors, posiitons):\n",
"\n",
" shape = b2d.polygon_shape(box=(5, 5), center=pos, angle=0)\n",
" pgDef = b2d.particle_group_def(\n",
" flags=b2d.ParticleFlag.waterParticle\n",
" | b2d.ParticleFlag.colorMixingParticle,\n",
" # group_flags=b2d.ParticleGroupFlag.solidParticleGroup,\n",
" shape=shape,\n",
" strength=1.0,\n",
" color=color,\n",
" )\n",
" group = psystem.create_particle_group(pgDef)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"\n",
"s = JupyterAsyncGui.Settings()\n",
"s.resolution = [1000,500]\n",
"s.scale = 8\n",
"s.fps = 40\n",
"\n",
"tb = b2d.testbed.run(ColorMixing, backend=JupyterAsyncGui, gui_settings=s)"
]
}
],
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,419 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "2859de40-f927-4790-b192-c5b0531058f7",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.2')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8ac3e93b-3e9e-4cd7-a183-0214b0dcb513",
"metadata": {},
"outputs": [],
"source": [
"from b2d.testbed import TestbedBase\n",
"import math\n",
"import numpy\n",
"import b2d\n",
"\n",
"class AngryShapes(TestbedBase):\n",
"\n",
" name = \"AngryShapes\"\n",
"\n",
" class Settings(TestbedBase.Settings):\n",
" substeps: int = 2\n",
"\n",
" def draw_segment(self, p1, p2, color, line_width=1):\n",
" screen_p1 = self._point(self.world_to_screen(p1))\n",
" screen_p2 = self._point(self.world_to_screen(p2))\n",
" screen_color = self._uint8_color(color)\n",
" screen_line_width = self._line_width(line_width)\n",
"\n",
" cv.line(self._image, screen_p1, screen_p2, screen_color, screen_line_width)\n",
"\n",
" def draw_polygon(self, vertices, color, line_width=1):\n",
" # todo add C++ function for this\n",
" screen_vertices = numpy.array(\n",
" [self._point(self.world_to_screen(v)) for v in vertices], dtype=\"int32\"\n",
" )\n",
" screen_color = self._uint8_color(color)\n",
" screen_line_width = self._line_width(line_width)\n",
"\n",
" cv.polylines(\n",
" self._image, [screen_vertices], True, screen_color, screen_line_width, 8\n",
" )\n",
"\n",
" def draw_solid_polygon(self, vertices, color):\n",
" # todo add C++ function for this\n",
" screen_vertices = numpy.array(\n",
" [self._point(self.world_to_screen(v)) for v in vertices], dtype=\"int32\"\n",
" )\n",
" screen_color = self._uint8_color(color)\n",
"\n",
" cv.fillPoly(self._image, [screen_vertices], screen_color, 8)\n",
"\n",
" def __init__(self, settings=None):\n",
" super(AngryShapes, self).__init__(settings=settings)\n",
"\n",
" self.targets = []\n",
" self.projectiles = []\n",
" self.marked_for_destruction = []\n",
" self.emitter = None\n",
"\n",
" # particle system\n",
" pdef = b2d.particle_system_def(\n",
" viscous_strength=0.9,\n",
" spring_strength=0.0,\n",
" damping_strength=100.5,\n",
" pressure_strength=1.0,\n",
" color_mixing_strength=0.05,\n",
" density=0.1,\n",
" )\n",
"\n",
" self.psystem = self.world.create_particle_system(pdef)\n",
" self.psystem.radius = 1\n",
" self.psystem.damping = 0.5\n",
"\n",
" self.build_outer_box()\n",
" self.build_castle()\n",
" self.build_launcher()\n",
" self.arm_launcher()\n",
" self.build_explosives()\n",
"\n",
" def build_outer_box(self):\n",
" # the outer box\n",
"\n",
" shape = b2d.edge_shape([(100, 0), (600, 0)])\n",
" box = self.world.create_static_body(\n",
" position=(0, 0), fixtures=b2d.fixture_def(shape=shape, friction=1)\n",
" )\n",
"\n",
" def build_target(self, pos):\n",
" t = self.world.create_dynamic_body(\n",
" position=pos,\n",
" fixtures=[\n",
" b2d.fixture_def(shape=b2d.circle_shape(radius=4), density=1.0),\n",
" b2d.fixture_def(\n",
" shape=b2d.circle_shape(radius=2, pos=(3, 3)), density=1.0\n",
" ),\n",
" b2d.fixture_def(\n",
" shape=b2d.circle_shape(radius=2, pos=(-3, 3)), density=1.0\n",
" ),\n",
" ],\n",
" linear_damping=0,\n",
" angular_damping=0,\n",
" user_data=\"target\",\n",
" )\n",
" self.targets.append(t)\n",
"\n",
" def build_castle(self):\n",
" def build_pyramid(offset, bar_shape, n):\n",
" def build_brick(pos, size):\n",
" hsize = [s / 2 for s in size]\n",
" self.world.create_dynamic_body(\n",
" position=(\n",
" pos[0] + hsize[0] + offset[0],\n",
" pos[1] + hsize[1] + offset[1],\n",
" ),\n",
" fixtures=b2d.fixture_def(\n",
" shape=b2d.polygon_shape(box=hsize), density=8\n",
" ),\n",
" user_data=\"brick\",\n",
" )\n",
"\n",
" bar_length = bar_shape[0]\n",
" bar_width = bar_shape[1]\n",
"\n",
" nxm = n\n",
" for y in range(nxm):\n",
" py = y * (bar_length + bar_width)\n",
" nx = nxm - y\n",
" for x in range(nx):\n",
" px = x * bar_length + y * (bar_length) / 2.0\n",
" if y + 1 < nxm - 1:\n",
" if x == 0:\n",
" px += bar_width / 2\n",
" if x + 1 == nx:\n",
" px -= bar_width / 2\n",
"\n",
" build_brick((px, py), (bar_width, bar_length))\n",
" if x < nx - 1:\n",
" self.build_target(\n",
" pos=(\n",
" px + offset[0] + bar_length / 2,\n",
" py + offset[1] + bar_width,\n",
" )\n",
" )\n",
" build_brick(\n",
" (px + bar_width / 2, py + bar_length),\n",
" (bar_length, bar_width),\n",
" )\n",
"\n",
" build_pyramid(offset=(100, 0), bar_shape=[40, 4], n=4)\n",
" build_pyramid(offset=(400, 0), bar_shape=[30, 3], n=4)\n",
"\n",
" def build_launcher(self):\n",
"\n",
" self.launcher_anchor_pos = (30, 0)\n",
" self.launcher_anchor = self.world.create_static_body(\n",
" position=self.launcher_anchor_pos\n",
" )\n",
"\n",
" def arm_launcher(self):\n",
" self.reload_time = None\n",
" self.is_armed = True\n",
" self.projectile_radius = 3\n",
" projectile_pos = (self.launcher_anchor_pos[0], self.launcher_anchor_pos[1] / 2)\n",
"\n",
" self.projectile = self.world.create_dynamic_body(\n",
" position=projectile_pos,\n",
" fixtures=b2d.fixture_def(\n",
" shape=b2d.circle_shape(radius=self.projectile_radius), density=100.0\n",
" ),\n",
" linear_damping=0,\n",
" angular_damping=0,\n",
" user_data=\"projectile\",\n",
" )\n",
" self.projectiles.append(self.projectile)\n",
" self.projectile_joint = self.world.create_distance_joint(\n",
" self.launcher_anchor, self.projectile, length=1, stiffness=10000\n",
" )\n",
" self.mouse_joint = None\n",
"\n",
" def build_explosives(self):\n",
" self.explosives = []\n",
"\n",
" def on_mouse_down(self, p):\n",
" if self.is_armed:\n",
" body = self.world.find_body(pos=p)\n",
" if body is not None and body.user_data is not None:\n",
" print(\"got body\")\n",
" if body.user_data == \"projectile\":\n",
" print(\"got projectile\")\n",
" kwargs = dict(\n",
" body_a=self.groundbody,\n",
" body_b=body,\n",
" target=p,\n",
" max_force=50000.0 * body.mass,\n",
" stiffness=10000.0,\n",
" )\n",
"\n",
" self.mouse_joint = self.world.create_mouse_joint(**kwargs)\n",
" body.awake = True\n",
" return True\n",
"\n",
" return False\n",
"\n",
" def on_mouse_move(self, p):\n",
" if self.is_armed:\n",
" if self.mouse_joint is not None:\n",
" self.mouse_joint.target = p\n",
" return True\n",
" return False\n",
"\n",
" def on_mouse_up(self, p):\n",
" if self.is_armed:\n",
" if self.mouse_joint is not None:\n",
" self.world.destroy_joint(self.mouse_joint)\n",
" if self.projectile_joint is not None:\n",
" self.world.destroy_joint(self.projectile_joint)\n",
" self.projectile_joint = None\n",
" self.mouse_joint = None\n",
" delta = self.launcher_anchor.position - b2d.vec2(p)\n",
" scaled_delta = delta * 50000.0\n",
" print(scaled_delta)\n",
"\n",
" self.projectile.apply_linear_impulse_to_center(scaled_delta, True)\n",
" self.reload_time = self.elapsed_time + 1.0\n",
" self.is_armed = False\n",
" return False\n",
"\n",
" def begin_contact(self, contact):\n",
" body_a = contact.body_a\n",
" body_b = contact.body_b\n",
" ud_a = body_a.user_data\n",
" ud_b = body_b.user_data\n",
" if ud_b == \"projectile\":\n",
" body_a, body_b = body_b, body_a\n",
" ud_a, ud_b = ud_b, ud_a\n",
" if ud_a == \"projectile\":\n",
"\n",
" if ud_b == \"target\" or ud_b == \"brick\":\n",
" self.marked_for_destruction.append(body_a)\n",
" emitter_def = b2d.RandomizedRadialEmitterDef()\n",
" emitter_def.emite_rate = 20000\n",
" emitter_def.lifetime = 0.7\n",
" emitter_def.enabled = True\n",
" emitter_def.inner_radius = 0.0\n",
" emitter_def.outer_radius = 1.0\n",
" emitter_def.velocity_magnitude = 1000.0\n",
" emitter_def.start_angle = 0\n",
" emitter_def.stop_angle = math.pi\n",
" emitter_def.transform = b2d.Transform(body_a.position, b2d.Rot(0))\n",
" self.emitter = b2d.RandomizedRadialEmitter(self.psystem, emitter_def)\n",
" self.emitter_die_time = self.elapsed_time + 0.02\n",
"\n",
" def pre_step(self, dt):\n",
"\n",
" if self.reload_time is not None:\n",
" if self.elapsed_time >= self.reload_time:\n",
" self.arm_launcher()\n",
"\n",
" # delete contact bodies\n",
" for body in self.marked_for_destruction:\n",
" if body in self.projectiles:\n",
" self.projectiles.remove(body)\n",
" self.world.destroy_body(body)\n",
" if body == self.projectile:\n",
" self.reload_time = self.elapsed_time + 1.0\n",
" self.marked_for_destruction = []\n",
"\n",
" # delete bodies which have fallen down\n",
" for body in self.world.bodies:\n",
" if body.position.y < -100:\n",
" if body.user_data == \"projectile\":\n",
" self.projectiles.remove(body)\n",
" if body.user_data == \"target\":\n",
" self.targets.remove(body)\n",
" self.world.destroy_body(body)\n",
"\n",
" # emmiter\n",
" if self.emitter is not None:\n",
" self.emitter.step(dt)\n",
" if self.elapsed_time >= self.emitter_die_time:\n",
" self.emitter = None\n",
"\n",
" def draw_target(self, target):\n",
" center = target.position\n",
" center_l = target.get_world_point((-3, 3))\n",
" center_r = target.get_world_point((3, 3))\n",
" eye_left = target.get_world_point((-1, 1))\n",
" eye_right = target.get_world_point((1, 1))\n",
" pink = [c / 255 for c in (248, 24, 148)]\n",
"\n",
" self.debug_draw.draw_solid_circle(\n",
" center=center, radius=4, axis=None, color=pink\n",
" )\n",
" self.debug_draw.draw_solid_circle(\n",
" center=center_l, radius=2, axis=None, color=pink\n",
" )\n",
" self.debug_draw.draw_solid_circle(\n",
" center=center_r, radius=2, axis=None, color=pink\n",
" )\n",
"\n",
" # schnautze\n",
" nose_center = target.get_world_point((0, -1))\n",
" nose_center_l = target.get_world_point((-0.3, -1))\n",
" nose_center_r = target.get_world_point((0.3, -1))\n",
"\n",
" self.debug_draw.draw_circle(\n",
" center=nose_center,\n",
" radius=2,\n",
" # axis=None,\n",
" color=(1, 1, 1),\n",
" line_width=0.2,\n",
" )\n",
" # eyes\n",
" for nose_center in [nose_center_l, nose_center_r]:\n",
" self.debug_draw.draw_solid_circle(\n",
" center=nose_center, radius=0.6, axis=None, color=(1, 1, 1)\n",
" )\n",
" # eyes\n",
" for eye_center in [eye_left, eye_right]:\n",
" self.debug_draw.draw_solid_circle(\n",
" center=eye_center, radius=1, axis=None, color=(1, 1, 1)\n",
" )\n",
" self.debug_draw.draw_solid_circle(\n",
" center=eye_center, radius=0.7, axis=None, color=(0, 0, 0)\n",
" )\n",
"\n",
" def draw_projectile(self, projectile):\n",
"\n",
" center = projectile.position\n",
" # center_l = target.get_world_point((-3,3))\n",
" # center_r = target.get_world_point(( 3,3))\n",
" eye_left = projectile.get_world_point((-1, 1))\n",
" eye_right = projectile.get_world_point((1, 1))\n",
"\n",
" self.debug_draw.draw_solid_circle(\n",
" center=center,\n",
" radius=self.projectile_radius * 1.1,\n",
" axis=None,\n",
" color=(1, 0, 0),\n",
" )\n",
"\n",
" # eyes\n",
" for eye_center in [eye_left, eye_right]:\n",
" self.debug_draw.draw_solid_circle(\n",
" center=eye_center, radius=1, axis=None, color=(1, 1, 1)\n",
" )\n",
" self.debug_draw.draw_solid_circle(\n",
" center=eye_center, radius=0.7, axis=None, color=(0, 0, 0)\n",
" )\n",
"\n",
" def post_debug_draw(self):\n",
" for target in self.targets:\n",
" self.draw_target(target)\n",
"\n",
" for projectile in self.projectiles:\n",
" self.draw_projectile(projectile)"
]
},
{
"cell_type": "markdown",
"id": "6df7c8b9-216b-4fd2-8ee8-aeec294e149d",
"metadata": {},
"source": [
"# Controlls\n",
"* To play this game, click and drag the red ball and release it to shot it.\n",
"* Use the mouse-wheel to zoom in/out, a\n",
"* Click and drag in the empty space to translate the view."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "df412e76-7a9a-4e1d-8bc7-c02e222e10dc",
"metadata": {},
"outputs": [],
"source": [
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"s = JupyterAsyncGui.Settings()\n",
"s.resolution = [1000,500]\n",
"s.scale = 2\n",
"s.translate = [100,100]\n",
"tb = b2d.testbed.run(AngryShapes, backend=JupyterAsyncGui, gui_settings=s);"
]
}
],
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,299 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.2')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy\n",
"import b2d\n",
"import math\n",
"import random\n",
"\n",
"from b2d.testbed import TestbedBase\n",
"\n",
"class Billiard(TestbedBase):\n",
"\n",
" name = \"Billiard\"\n",
"\n",
" def __init__(self, settings=None):\n",
" super(Billiard, self).__init__(gravity=(0, 0), settings=settings)\n",
" dimensions = [30, 50]\n",
" self.dimensions = dimensions\n",
"\n",
" # the outer box\n",
" box_shape = b2d.ChainShape()\n",
" box_shape.create_loop(\n",
" [\n",
" (0, 0),\n",
" (0, dimensions[1]),\n",
" (dimensions[0], dimensions[1]),\n",
" (dimensions[0], 0),\n",
" ]\n",
" )\n",
" self.ball_radius = 1\n",
" box = self.world.create_static_body(\n",
" position=(0, 0), fixtures=b2d.fixture_def(shape=box_shape, friction=0)\n",
" )\n",
"\n",
" self.place_balls()\n",
" self.place_pockets()\n",
"\n",
" # mouse interaction\n",
" self._selected_ball = None\n",
" self._selected_ball_pos = None\n",
" self._last_pos = None\n",
"\n",
" # balls to be destroyed in the next step\n",
" # since they are in the pocket\n",
" self._to_be_destroyed = []\n",
"\n",
" def place_pockets(self):\n",
" pocket_radius = 1\n",
" self.pockets = []\n",
"\n",
" def place_pocket(position):\n",
" pocket_shape = b2d.circle_shape(radius=pocket_radius / 3)\n",
" pocket = self.world.create_static_body(\n",
" position=position,\n",
" fixtures=b2d.fixture_def(shape=pocket_shape, is_sensor=True),\n",
" user_data=(\"pocket\", None),\n",
" )\n",
" self.pockets.append(pocket)\n",
"\n",
" d = pocket_radius / 2\n",
"\n",
" place_pocket(position=(0 + d, 0 + d))\n",
" place_pocket(position=(self.dimensions[0] - d, 0 + d))\n",
"\n",
" place_pocket(position=(0 + d, self.dimensions[1] / 2))\n",
" place_pocket(position=(self.dimensions[0] - d, self.dimensions[1] / 2))\n",
"\n",
" place_pocket(position=(0 + d, self.dimensions[1] - d))\n",
" place_pocket(position=(self.dimensions[0] - d, self.dimensions[1] - d))\n",
"\n",
" def place_balls(self):\n",
" self.balls = []\n",
"\n",
" base_colors = [\n",
" (1, 1, 0),\n",
" (0, 0, 1),\n",
" (1, 0, 0),\n",
" (1, 0, 1),\n",
" (1, 0.6, 0),\n",
" (0, 1, 0),\n",
" (0.7, 0.4, 0.4),\n",
" ]\n",
" colors = []\n",
" for color in base_colors:\n",
" # ``full`` ball\n",
" colors.append((color, color))\n",
" # ``half`` ball (half white)\n",
" colors.append((color, (1, 1, 1)))\n",
"\n",
" random.shuffle(colors)\n",
" colors.insert(4, ((0, 0, 0), (0, 0, 0))) # black\n",
"\n",
" n_y = 5\n",
" c_x = self.dimensions[0] / 2\n",
" diameter = (self.ball_radius * 2) * 1.01\n",
"\n",
" bi = 0\n",
" for y in range(n_y):\n",
"\n",
" py = y * diameter * 0.5 * math.sqrt(3)\n",
" n_x = y + 1\n",
" ox = diameter * (n_y - y) / 2\n",
" for x in range(y + 1):\n",
" position = (x * diameter + 10 + ox, py + 30)\n",
" self.create_billard_ball(position=position, color=colors[bi])\n",
" bi += 1\n",
"\n",
" self.create_billard_ball(position=(c_x, 10), color=((1, 1, 1), (1, 1, 1)))\n",
"\n",
" def create_billard_ball(self, position, color):\n",
"\n",
" ball = self.world.create_dynamic_body(\n",
" position=position,\n",
" fixtures=b2d.fixture_def(\n",
" shape=b2d.circle_shape(radius=self.ball_radius),\n",
" density=1.0,\n",
" restitution=0.8,\n",
" ),\n",
" linear_damping=0.8,\n",
" user_data=(\"ball\", color),\n",
" fixed_rotation=True,\n",
" )\n",
" self.balls.append(ball)\n",
"\n",
" def begin_contact(self, contact):\n",
" body_a = contact.body_a\n",
" body_b = contact.body_b\n",
"\n",
" ud_a = body_a.user_data\n",
" ud_b = body_b.user_data\n",
" if ud_a is None or ud_b is None:\n",
" return\n",
"\n",
" if ud_b[0] == \"ball\":\n",
" body_a, body_b = body_b, body_a\n",
" ud_a, ud_b = ud_b, ud_a\n",
"\n",
" if ud_a[0] == \"ball\" and ud_b[0] == \"pocket\":\n",
" self._to_be_destroyed.append(body_a)\n",
"\n",
" def pre_step(self, dt):\n",
" for b in self._to_be_destroyed:\n",
" self.balls.remove(b)\n",
" self.world.destroy_body(b)\n",
" self._to_be_destroyed = []\n",
"\n",
" def ball_at_position(self, pos):\n",
" body = self.world.find_body(pos)\n",
" if body is not None:\n",
" user_data = body.user_data\n",
" if user_data is not None and user_data[0] == \"ball\":\n",
" return body\n",
" return None\n",
"\n",
" def on_mouse_down(self, pos):\n",
" body = self.ball_at_position(pos)\n",
" if body is not None:\n",
" self._selected_ball = body\n",
" self._selected_ball_pos = pos\n",
" return True\n",
"\n",
" return False\n",
"\n",
" def on_mouse_move(self, pos):\n",
" if self._selected_ball is not None:\n",
" self._last_pos = pos\n",
" return True\n",
" return False\n",
"\n",
" def on_mouse_up(self, pos):\n",
" if self._selected_ball is not None:\n",
" self._last_pos = pos\n",
" # if the mouse is in the starting ball itself we do nothing\n",
" if self.ball_at_position(pos) != self._selected_ball:\n",
" delta = b2d.vec2(self._selected_ball_pos) - b2d.vec2(self._last_pos)\n",
" delta *= 100.0\n",
" self._selected_ball.apply_linear_impulse(\n",
" delta, self._selected_ball_pos, True\n",
" )\n",
" self._selected_ball = None\n",
" self._selected_ball_pos = None\n",
" self._last_pos = None\n",
" return False\n",
"\n",
" def post_debug_draw(self):\n",
"\n",
" for pocket in self.pockets:\n",
" self.debug_draw.draw_solid_circle(\n",
" pocket.position, self.ball_radius, (1, 0), (1, 1, 1)\n",
" )\n",
"\n",
" for ball in self.balls:\n",
" _, (color0, color1) = ball.user_data\n",
"\n",
" self.debug_draw.draw_solid_circle(\n",
" ball.position, self.ball_radius, (1, 0), color0\n",
" )\n",
" self.debug_draw.draw_solid_circle(\n",
" ball.position, self.ball_radius / 2, (1, 0), color1\n",
" )\n",
" self.debug_draw.draw_circle(\n",
" ball.position, self.ball_radius, (1, 1, 1), line_width=0.1\n",
" )\n",
"\n",
" if self._selected_ball is not None:\n",
"\n",
" # draw circle around selected ball\n",
" self.debug_draw.draw_circle(\n",
" self._selected_ball.position,\n",
" self.ball_radius * 2,\n",
" (1, 1, 1),\n",
" line_width=0.2,\n",
" )\n",
"\n",
" # mark position on selected ball with red dot\n",
" self.debug_draw.draw_solid_circle(\n",
" self._selected_ball_pos, self.ball_radius * 0.2, (1, 0), (1, 0, 0)\n",
" )\n",
"\n",
" # draw the line between marked pos on ball and last pos\n",
" if self._last_pos is not None:\n",
" self.debug_draw.draw_segment(\n",
" self._selected_ball_pos, self._last_pos, (1, 1, 1), line_width=0.2\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Controlls\n",
"* To play this game, click and hold inside a billiard ball, move and release the mouse to shoot the ball.\n",
"* Use the mouse-wheel to zoom in/out, a\n",
"* Click and drag in the empty space to translate the view."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"backend = JupyterAsyncGui\n",
"s = backend.Settings()\n",
"s.resolution = [500,600]\n",
"s.scale = 8\n",
"s.fps = 40\n",
"s.translate = [125,100]\n",
"b2d.testbed.run(Billiard, backend=backend, gui_settings=s);"
]
},
{
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,575 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('networkx')\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.2')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import b2d\n",
"from b2d.testbed import TestbedBase\n",
"import math\n",
"import random\n",
"import numpy\n",
"from functools import partial\n",
"import networkx\n",
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"\n",
"def best_pairwise_distance(data, f, distance):\n",
" n = len(data)\n",
" best = (None, None, float(\"inf\"))\n",
" for i in range(n - 1):\n",
" da = f(data[i])\n",
" for j in range(i + 1, n):\n",
" db = f(data[j])\n",
"\n",
" d = distance(da, db)\n",
" if d < best[2]:\n",
" best = (i, j, d)\n",
" return best\n",
"\n",
"class Level(object):\n",
" def __init__(self, testbed):\n",
" self.testbed = testbed\n",
" self.world = testbed.world\n",
"\n",
" self.gap_size = 15\n",
" self.kill_sensors_height = 0.5\n",
" self.usable_size = 20\n",
" self.h = 10\n",
" self.end_zone_height = 3\n",
"\n",
" self.outline_verts = [\n",
" (0, self.h),\n",
" (0, 2 * self.h),\n",
" (0, self.h),\n",
" (self.usable_size, self.h),\n",
" (self.usable_size, 0),\n",
" (self.usable_size + self.gap_size, 0),\n",
" (self.usable_size + self.gap_size, self.h),\n",
" (2 * self.usable_size + self.gap_size, self.h),\n",
" (2 * self.usable_size + self.gap_size, 2 * self.h),\n",
" ]\n",
"\n",
" # outline of the level\n",
" shape = b2d.chain_shape(vertices=numpy.flip(self.outline_verts, axis=0))\n",
" self.outline = self.world.create_static_body(position=(0, 0), shape=shape)\n",
"\n",
" # kill sensors\n",
" self.kill_sensor_pos = (\n",
" self.usable_size + self.gap_size / 2,\n",
" self.kill_sensors_height / 2,\n",
" )\n",
"\n",
" shape = b2d.polygon_shape(box=(self.gap_size / 2, self.kill_sensors_height / 2))\n",
" self._kill_sensor = self.world.create_static_body(\n",
" position=self.kill_sensor_pos,\n",
" fixtures=b2d.fixture_def(shape=shape, is_sensor=True),\n",
" )\n",
" self._kill_sensor.user_data = \"destroyer\"\n",
"\n",
" # end sensor\n",
" shape = b2d.polygon_shape(box=(self.usable_size / 2, self.end_zone_height / 2))\n",
" self._end_sensor = self.world.create_static_body(\n",
" position=(\n",
" 1.5 * self.usable_size + self.gap_size,\n",
" self.h + self.end_zone_height / 2,\n",
" ),\n",
" fixtures=b2d.fixture_def(shape=shape, is_sensor=True),\n",
" )\n",
" self._end_sensor.user_data = \"goal\"\n",
"\n",
" goo_radius = 1\n",
" a = self.testbed.insert_goo(\n",
" pos=(self.usable_size / 3, self.h + goo_radius), static=True\n",
" )\n",
" b = self.testbed.insert_goo(\n",
" pos=(self.usable_size * 2 / 3, self.h + goo_radius), static=True\n",
" )\n",
" c = self.testbed.insert_goo(\n",
" pos=(self.usable_size * 1 / 2, self.h + goo_radius + 4), static=False\n",
" )\n",
"\n",
" self.testbed.connect_goos(a, b)\n",
" self.testbed.connect_goos(a, c)\n",
" self.testbed.connect_goos(b, c)\n",
"\n",
" def draw(self, debug_draw):\n",
"\n",
" # draw outline\n",
" for i in range(len(self.outline_verts) - 1):\n",
" debug_draw.draw_segment(\n",
" self.outline_verts[i],\n",
" self.outline_verts[i + 1],\n",
" color=(1, 1, 0),\n",
" line_width=0.3,\n",
" )\n",
"\n",
" left = list(self.kill_sensor_pos)\n",
" left[0] -= self.gap_size / 2\n",
" left[1] += self.kill_sensors_height / 2\n",
"\n",
" right = list(self.kill_sensor_pos)\n",
" right[0] += self.gap_size / 2\n",
" right[1] += self.kill_sensors_height / 2\n",
" debug_draw.draw_segment(left, right, (1, 0, 0), line_width=0.4)\n",
"\n",
"\n",
"class FindGoos(b2d.QueryCallback):\n",
" def __init__(self):\n",
" super(FindGoos, self).__init__()\n",
" self.goos = []\n",
"\n",
" def report_fixture(self, fixture):\n",
" body = fixture.body\n",
" if body.user_data == \"goo\":\n",
" self.goos.append(body)\n",
" return True\n",
"\n",
"\n",
"class Goo(TestbedBase):\n",
"\n",
" name = \"Goo\"\n",
"\n",
" def __init__(self, settings=None):\n",
" super(Goo, self).__init__(settings=settings)\n",
"\n",
" self.goo_graph = networkx.Graph()\n",
" self.level = Level(testbed=self)\n",
"\n",
" # mouse related\n",
" self.last_mouse_pos = None\n",
" self.is_mouse_down = False\n",
" self.could_place_goo_when_mouse_was_down = False\n",
"\n",
" # callback to draw tentative placement\n",
" self.draw_callback = None\n",
"\n",
" # goos marked for destruction\n",
" self.goo_to_destroy = []\n",
"\n",
" # joints marked for destruction\n",
" self.joints_to_destroy = []\n",
" self.gamma = 0.003\n",
" self.break_threshold = 0.5\n",
"\n",
" # time point when goo can be inserted\n",
" self.insert_time_point = 0\n",
" self.insert_delay = 1.0\n",
"\n",
" # handle finishing of level\n",
" self.with_goal_contact = dict()\n",
"\n",
" # amount of seconds one has to be in the finishing zone\n",
" self.win_delay = 3.0\n",
"\n",
" # particle system will be defined an used on win!\n",
" # this is then used for some kind of fireworks\n",
" self.psystem = None\n",
" self.emitter = None\n",
" self.emitter_stop_time = None\n",
" self.emitter_start_time = None\n",
"\n",
" # trigger some fireworks on win\n",
" def on_win(self, win_body):\n",
"\n",
" if self.psystem is None:\n",
" # particle system\n",
" pdef = b2d.particle_system_def(\n",
" viscous_strength=0.9,\n",
" spring_strength=0.0,\n",
" damping_strength=100.5,\n",
" pressure_strength=1.0,\n",
" color_mixing_strength=0.05,\n",
" density=0.1,\n",
" )\n",
"\n",
" self.psystem = self.world.create_particle_system(pdef)\n",
" self.psystem.radius = 0.1\n",
" self.psystem.damping = 0.5\n",
"\n",
" emitter_def = b2d.RandomizedRadialEmitterDef()\n",
" emitter_def.emite_rate = 2000\n",
" emitter_def.lifetime = 0.9\n",
" emitter_def.enabled = True\n",
" emitter_def.inner_radius = 0.0\n",
" emitter_def.outer_radius = 0.1\n",
" emitter_def.velocity_magnitude = 1000.0\n",
" emitter_def.start_angle = 0\n",
" emitter_def.stop_angle = 2 * math.pi\n",
" emitter_def.transform = b2d.Transform(\n",
" win_body.position + b2d.vec2(0, 20), b2d.Rot(0)\n",
" )\n",
" self.emitter = b2d.RandomizedRadialEmitter(self.psystem, emitter_def)\n",
" self.emitter_stop_time = self.elapsed_time + 0.2\n",
"\n",
" def draw_goo(self, pos, angle, body=None):\n",
" self.debug_draw.draw_solid_circle(pos, 1, axis=None, color=(1, 0, 1))\n",
" self.debug_draw.draw_circle(pos, 1.1, (1, 1, 1), line_width=0.1)\n",
"\n",
" if body is not None:\n",
" centers = [\n",
" body.get_world_point((-0.3, 0.2)),\n",
" body.get_world_point((0.3, 0.2)),\n",
" ]\n",
" for center in centers:\n",
" self.debug_draw.draw_solid_circle(\n",
" center, 0.4, axis=None, color=(1, 1, 1)\n",
" )\n",
" self.debug_draw.draw_solid_circle(\n",
" center, 0.2, axis=None, color=(0, 0, 0)\n",
" )\n",
"\n",
" def draw_edge(self, pos_a, pos_b, stress):\n",
" no_stress = numpy.array([1, 1, 1])\n",
" has_stress = numpy.array([1, 0, 0])\n",
" color = (1.0 - stress) * no_stress + stress * has_stress\n",
" color = tuple([float(c) for c in color])\n",
" self.debug_draw.draw_segment(pos_a, pos_b, color=color, line_width=0.4)\n",
"\n",
" def insert_goo(self, pos, static=False):\n",
" if static:\n",
" f = self.world.create_static_body\n",
" else:\n",
" f = self.world.create_dynamic_body\n",
"\n",
" goo = f(\n",
" position=pos,\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=1), density=1),\n",
" user_data=\"goo\",\n",
" )\n",
" self.goo_graph.add_node(goo)\n",
" return goo\n",
"\n",
" def connect_goos(self, goo_a, goo_b):\n",
" length = (goo_a.position - goo_b.position).length\n",
" joint = self.world.create_distance_joint(\n",
" goo_a,\n",
" goo_b,\n",
" stiffness=500,\n",
" damping=0.1,\n",
" length=length,\n",
" user_data=dict(length=length, stress=0),\n",
" )\n",
" self.goo_graph.add_edge(goo_a, goo_b, joint=joint)\n",
"\n",
" def query_placement(self, pos):\n",
"\n",
" radius = 8\n",
"\n",
" # find all goos in around pos\n",
" pos = b2d.vec2(pos)\n",
" box = b2d.aabb(\n",
" lower_bound=pos - b2d.vec2(radius, radius),\n",
" upper_bound=pos + b2d.vec2(radius, radius),\n",
" )\n",
" query = FindGoos()\n",
" self.world.query_aabb(query, box)\n",
" goos = query.goos\n",
" n_goos = len(goos)\n",
"\n",
" if n_goos >= 2:\n",
"\n",
" # try to insert to goo as edge between\n",
" # 2 existing goos\n",
" def distance(a, b, p):\n",
" if self.goo_graph.has_edge(a[0], b[0]):\n",
" return float(\"inf\")\n",
" return numpy.linalg.norm((a[1] + b[1]) / 2 - p)\n",
"\n",
" i, j, best_dist = best_pairwise_distance(\n",
" goos,\n",
" f=lambda goo: (goo, numpy.array(goo.position)),\n",
" distance=partial(distance, p=pos),\n",
" )\n",
"\n",
" if best_dist < 0.8:\n",
"\n",
" def draw_callback():\n",
" self.draw_edge(goos[i].position, goos[j].position, stress=0)\n",
"\n",
" def insert_callack():\n",
" self.connect_goos(goos[i], goos[j])\n",
"\n",
" return True, draw_callback, insert_callack\n",
"\n",
" # try to insert the goo as brand new\n",
" # goo and connect it with 2 existing goos\n",
" f = lambda goo: (goo, (goo.position - b2d.vec2(pos)).length)\n",
"\n",
" def distance(a, b):\n",
" if not self.goo_graph.has_edge(a[0], b[0]):\n",
" return float(\"inf\")\n",
" return a[1] + b[1]\n",
"\n",
" i, j, best_dist = best_pairwise_distance(goos, f=f, distance=distance)\n",
" if best_dist < float(\"inf\"):\n",
"\n",
" def draw_callback():\n",
"\n",
" self.draw_edge(pos, goos[i].position, stress=0)\n",
" self.draw_edge(pos, goos[j].position, stress=0)\n",
" self.draw_goo(pos, angle=None)\n",
"\n",
" def insert_callack():\n",
" goo = self.insert_goo(pos=pos)\n",
" self.connect_goos(goo, goos[i])\n",
" self.connect_goos(goo, goos[j])\n",
"\n",
" return True, draw_callback, insert_callack\n",
"\n",
" return False, None, None\n",
"\n",
" def on_mouse_down(self, pos):\n",
" self.last_mouse_pos = pos\n",
" self.is_mouse_down = True\n",
" can_be_placed, draw_callback, insert_callback = self.query_placement(pos)\n",
" self.could_place_goo_when_mouse_was_down = can_be_placed\n",
" if can_be_placed:\n",
" if self.elapsed_time < self.insert_time_point:\n",
" return True\n",
" self.draw_callback = draw_callback\n",
" return True\n",
" return False\n",
"\n",
" def on_mouse_move(self, pos):\n",
" self.last_mouse_pos = pos\n",
" if self.is_mouse_down:\n",
" can_be_placed, draw_callback, insert_callback = self.query_placement(pos)\n",
" if can_be_placed:\n",
" if self.elapsed_time < self.insert_time_point:\n",
" return True\n",
" self.draw_callback = draw_callback\n",
" return True\n",
" else:\n",
" self.draw_callback = None\n",
" return self.could_place_goo_when_mouse_was_down\n",
"\n",
" def on_mouse_up(self, pos):\n",
" self.last_mouse_pos = pos\n",
" self.is_mouse_down = False\n",
" self.draw_callback = None\n",
" can_be_placed, draw_callback, insert_callback = self.query_placement(pos)\n",
" if can_be_placed:\n",
" if self.elapsed_time < self.insert_time_point:\n",
" return True\n",
" # self.draw_callback = draw_callback\n",
" insert_callback()\n",
" self.insert_time_point = self.elapsed_time + self.insert_delay\n",
" return True\n",
" return False\n",
"\n",
" def begin_contact(self, contact):\n",
" body_a = contact.body_a\n",
" body_b = contact.body_b\n",
" if body_b.user_data == \"goo\":\n",
" body_a, body_b = body_b, body_a\n",
"\n",
" user_data_a = body_a.user_data\n",
" user_data_b = body_b.user_data\n",
" if body_a.user_data == \"goo\":\n",
" if user_data_b == \"destroyer\":\n",
" self.goo_to_destroy.append(body_a)\n",
" elif user_data_b == \"goal\":\n",
" self.with_goal_contact[body_a] = self.elapsed_time + self.win_delay\n",
"\n",
" def end_contact(self, contact):\n",
" body_a = contact.body_a\n",
" body_b = contact.body_b\n",
" if body_b.user_data == \"goo\":\n",
" body_a, body_b = body_b, body_a\n",
"\n",
" user_data_a = body_a.user_data\n",
" user_data_b = body_b.user_data\n",
" if body_a.user_data == \"goo\":\n",
" if user_data_b == \"goal\":\n",
" if body_a in self.with_goal_contact:\n",
" del self.with_goal_contact[body_a]\n",
"\n",
" def pre_step(self, dt):\n",
"\n",
" # query if goo can be inserted\n",
" if (\n",
" self.is_mouse_down\n",
" and self.last_mouse_pos is not None\n",
" and self.draw_callback is None\n",
" ):\n",
" can_be_placed, draw_callback, insert_callback = self.query_placement(\n",
" self.last_mouse_pos\n",
" )\n",
" if can_be_placed and self.elapsed_time >= self.insert_time_point:\n",
" self.draw_callback = draw_callback\n",
"\n",
" # compute joint stress\n",
" for goo_a, goo_b, joint in self.goo_graph.edges(data=\"joint\"):\n",
" jd = joint.user_data\n",
"\n",
" # distance based stress\n",
" insert_length = jd[\"length\"]\n",
" length = (goo_a.position - goo_b.position).length\n",
"\n",
" d = length - insert_length\n",
" if d > 0:\n",
"\n",
" # reaction force based stress\n",
" rf = joint.get_reaction_force(30).length\n",
"\n",
" normalized_rf = 1.0 - math.exp(-rf * self.gamma)\n",
"\n",
" jd[\"stress\"] = normalized_rf / self.break_threshold\n",
" if normalized_rf > self.break_threshold:\n",
" self.joints_to_destroy.append((goo_a, goo_b, joint))\n",
"\n",
" else:\n",
" jd[\"stress\"] = 0\n",
"\n",
" for goo_a, goo_b, joint in self.joints_to_destroy:\n",
" self.goo_graph.remove_edge(u=goo_a, v=goo_b)\n",
" self.world.destroy_joint(joint)\n",
" self.joints_to_destroy = []\n",
"\n",
" # destroy goos\n",
" for goo in self.goo_to_destroy:\n",
" self.goo_graph.remove_node(goo)\n",
" self.world.destroy_body(goo)\n",
"\n",
" # destroy all with wrong degree\n",
" while True:\n",
" destroyed_any = False\n",
" to_remove = []\n",
" for goo in self.goo_graph.nodes:\n",
" if self.goo_graph.degree(goo) < 2:\n",
" destroyed_any = True\n",
" to_remove.append(goo)\n",
" if not destroyed_any:\n",
" break\n",
" for goo in to_remove:\n",
" self.goo_graph.remove_node(goo)\n",
" self.world.destroy_body(goo)\n",
" self.goo_to_destroy = []\n",
"\n",
" # check if we are done\n",
" for goo, finish_time in self.with_goal_contact.items():\n",
" if finish_time <= self.elapsed_time:\n",
" self.on_win(goo)\n",
"\n",
" if self.emitter is not None:\n",
" if self.emitter_stop_time is not None:\n",
" if self.elapsed_time > self.emitter_stop_time:\n",
" self.emitter.enabled = False\n",
" self.emitter_start_time = self.elapsed_time + 0.4\n",
" self.emitter_stop_time = None\n",
" p = list(self.emitter.position)\n",
" p[0] += (random.random() - 0.5) * 10.0\n",
" p[1] += (random.random() - 0.5) * 2.0\n",
" self.emitter.position = p\n",
" if self.emitter_start_time is not None:\n",
" if self.elapsed_time > self.emitter_start_time:\n",
" self.emitter.enabled = True\n",
" self.emitter_start_time = None\n",
" self.emitter_stop_time = self.elapsed_time + 0.2\n",
" self.emitter.step(dt)\n",
"\n",
" def post_debug_draw(self):\n",
"\n",
" self.level.draw(self.debug_draw)\n",
"\n",
" # draw mouse when mouse is down\n",
" if (\n",
" self.is_mouse_down\n",
" and self.last_mouse_pos is not None\n",
" and self.draw_callback is None\n",
" ):\n",
" d = (self.insert_time_point - self.elapsed_time) / self.insert_delay\n",
" if d > 0:\n",
" d = d * math.pi * 2\n",
" x = math.sin(d)\n",
" y = math.cos(d)\n",
" p = self.last_mouse_pos[0] + x, self.last_mouse_pos[1] + y\n",
" self.debug_draw.draw_segment(\n",
" p, self.last_mouse_pos, color=(1, 0, 0), line_width=0.2\n",
" )\n",
" self.debug_draw.draw_circle(\n",
" self.last_mouse_pos, 1, (1, 0, 0), line_width=0.2\n",
" )\n",
"\n",
" # draw the tentative placement\n",
" if self.draw_callback is not None:\n",
" self.draw_callback()\n",
"\n",
" for goo_a, goo_b, joint in self.goo_graph.edges(data=\"joint\"):\n",
" self.draw_edge(\n",
" goo_a.position, goo_b.position, stress=joint.user_data[\"stress\"]\n",
" )\n",
"\n",
" for goo in self.goo_graph:\n",
" self.draw_goo(goo.position, goo.angle, body=goo)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Controlls\n",
"* To play this game, click and drag next to the existing \"goos\"\n",
"* try to bridge the tiny gap\n",
"* Use the mouse-wheel to zoom in/out, a\n",
"* Click and drag in the empty space to translate the view."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"s = JupyterAsyncGui.Settings()\n",
"s.resolution = [1000,500]\n",
"s.scale = 8\n",
"tb = b2d.testbed.run(Goo, backend=JupyterAsyncGui, gui_settings=s);"
]
},
{
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,282 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "f7b8452d-61fe-4356-8084-cac603096fef",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.2')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0bfa61e4-9817-4bea-aa66-6a660a423ae6",
"metadata": {},
"outputs": [],
"source": [
"from b2d.testbed import TestbedBase\n",
"import random\n",
"import numpy\n",
"import b2d\n",
"import math\n",
"\n",
"class Rocket(TestbedBase):\n",
"\n",
" name = \"Rocket\"\n",
"\n",
" def __init__(self, settings=None):\n",
" super(Rocket, self).__init__(gravity=(0, 0), settings=settings)\n",
"\n",
" # gravitational constant\n",
" self.gravitational_constant = 6.0\n",
"\n",
" self.planets = {}\n",
"\n",
" # home planet\n",
" home_planet = self.world.create_kinematic_body(\n",
" position=(10, 0),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=20)),\n",
" user_data=\"home_planet\",\n",
" )\n",
"\n",
" # target planet\n",
" target_planet = self.world.create_kinematic_body(\n",
" position=(100, 100),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=10)),\n",
" user_data=\"target_planet\",\n",
" )\n",
"\n",
" # black hole\n",
" black_hole = self.world.create_kinematic_body(\n",
" position=(0, 400),\n",
" fixtures=b2d.fixture_def(shape=b2d.circle_shape(radius=1)),\n",
" user_data=\"black_hole\",\n",
" )\n",
"\n",
" self.planets = {\n",
" home_planet: dict(radius=20, density=1, color=(0, 0.2, 1)),\n",
" target_planet: dict(radius=10, density=1, color=(0.7, 0.7, 0.7)),\n",
" black_hole: dict(radius=1, density=10000, color=(0.1, 0.1, 0.1)),\n",
" }\n",
"\n",
" # a tiny rocket\n",
" self.rocket = self.world.create_dynamic_body(\n",
" position=(10, 10),\n",
" fixtures=[\n",
" b2d.fixture_def(shape=b2d.polygon_shape(box=[1, 1]), density=1),\n",
" b2d.fixture_def(\n",
" shape=b2d.polygon_shape(vertices=[(-1, 1), (0, 4), (1, 1)]),\n",
" density=1,\n",
" ),\n",
" ],\n",
" angular_damping=0.5,\n",
" linear_damping=0.2,\n",
" user_data=\"rocket\",\n",
" )\n",
" # check if the rocket is gone\n",
" self.touched_black_hole = False\n",
"\n",
" # particle system\n",
" pdef = b2d.particle_system_def(\n",
" viscous_strength=0.9,\n",
" spring_strength=0.0,\n",
" damping_strength=100.5,\n",
" pressure_strength=1.0,\n",
" color_mixing_strength=0.05,\n",
" density=0.1,\n",
" )\n",
"\n",
" psystem = self.world.create_particle_system(pdef)\n",
" psystem.radius = 0.1\n",
" psystem.damping = 0.5\n",
"\n",
" self.emitters = []\n",
" self.key_map = {\"w\": 0, \"a\": 1, \"d\": 2}\n",
"\n",
" angle_width = (math.pi * 2) / 16\n",
" emitter_def = b2d.RandomizedRadialEmitterDef()\n",
" emitter_def.emite_rate = 2000\n",
" emitter_def.lifetime = 1.0\n",
" emitter_def.enabled = False\n",
" emitter_def.inner_radius = 1\n",
" emitter_def.outer_radius = 1\n",
" emitter_def.velocity_magnitude = 10.0\n",
" emitter_def.start_angle = math.pi / 2 - angle_width / 2.0\n",
" emitter_def.stop_angle = math.pi / 2 + angle_width / 2.0\n",
" emitter_def.body = self.rocket\n",
"\n",
" delta = 0.2\n",
" self.emitter_local_anchors = [\n",
" (0, -delta), # main\n",
" (-delta, -0.5), # left,\n",
" (delta, -0.5), # right\n",
" ]\n",
" self.emitter_local_rot = [math.pi, math.pi / 2, -math.pi / 2] # main\n",
"\n",
" # main trust\n",
" emitter_def.emite_rate = 2000\n",
" world_anchor = self.rocket.get_world_point(self.emitter_local_anchors[0])\n",
" emitter_def.transform = b2d.Transform(\n",
" world_anchor, b2d.Rot(self.emitter_local_rot[0])\n",
" )\n",
" emitter = b2d.RandomizedRadialEmitter(psystem, emitter_def)\n",
" self.emitters.append(emitter)\n",
"\n",
" # left\n",
" emitter_def.emite_rate = 200\n",
" world_anchor = self.rocket.get_world_point(self.emitter_local_anchors[1])\n",
" emitter_def.transform = b2d.Transform(\n",
" world_anchor, b2d.Rot(self.emitter_local_rot[1])\n",
" )\n",
" emitter = b2d.RandomizedRadialEmitter(psystem, emitter_def)\n",
" self.emitters.append(emitter)\n",
"\n",
" # right\n",
" emitter_def.emite_rate = 200\n",
" world_anchor = self.rocket.get_world_point(self.emitter_local_anchors[1])\n",
" emitter_def.transform = b2d.Transform(\n",
" world_anchor, b2d.Rot(self.emitter_local_rot[1])\n",
" )\n",
" emitter = b2d.RandomizedRadialEmitter(psystem, emitter_def)\n",
" self.emitters.append(emitter)\n",
"\n",
" def pre_step(self, dt):\n",
"\n",
" # check if the rocket has died\n",
" if self.touched_black_hole:\n",
" if self.rocket is not None:\n",
" self.world.destroy_body(self.rocket)\n",
" self.rocket = None\n",
" else:\n",
" rocket_center = self.rocket.world_center\n",
" rocket_mass = self.rocket.mass\n",
" # compute gravitational forces\n",
" net_force = numpy.zeros([2])\n",
" for planet, planet_def in self.planets.items():\n",
" radius = planet_def[\"radius\"]\n",
" planet_center = planet.position\n",
" planet_mass = planet_def[\"density\"] * radius ** 2 * math.pi\n",
" delta = rocket_center - planet_center\n",
" distance = delta.normalize()\n",
" f = (\n",
" -self.gravitational_constant\n",
" * rocket_mass\n",
" * planet_mass\n",
" / (distance * distance)\n",
" )\n",
" net_force += delta * f\n",
" f = float(net_force[0]), float(net_force[1])\n",
" self.rocket.apply_force_to_center(f)\n",
"\n",
" # run the rockets engines\n",
" for emitter, local_anchor, local_rotation in zip(\n",
" self.emitters, self.emitter_local_anchors, self.emitter_local_rot\n",
" ):\n",
" world_anchor = self.rocket.get_world_point(local_anchor)\n",
" emitter.position = world_anchor\n",
" emitter.angle = self.rocket.angle + local_rotation\n",
" emitter.step(dt)\n",
"\n",
" def begin_contact(self, contact):\n",
" body_a = contact.body_a\n",
" body_b = contact.body_b\n",
" if body_b.user_data == \"rocket\":\n",
" body_a, body_b = body_b, body_a\n",
"\n",
" user_data_a = body_a.user_data\n",
" user_data_b = body_b.user_data\n",
" if body_a.user_data == \"rocket\":\n",
" if user_data_b == \"black_hole\":\n",
" self.touched_black_hole = True\n",
"\n",
" def on_keyboard_down(self, key):\n",
" if key in self.key_map:\n",
" self.emitters[self.key_map[key]].enabled = True\n",
" return True\n",
" return False\n",
"\n",
" def on_keyboard_up(self, key):\n",
" if key in self.key_map:\n",
" self.emitters[self.key_map[key]].enabled = False\n",
" return False\n",
" return False\n",
"\n",
" def pre_debug_draw(self):\n",
" pass\n",
"\n",
" def post_debug_draw(self):\n",
" for planet, planet_def in self.planets.items():\n",
" pos = planet.position\n",
" self.debug_draw.draw_solid_circle(\n",
" pos, planet_def[\"radius\"] + 0.1, axis=None, color=planet_def[\"color\"]\n",
" )\n",
" if planet.user_data == \"black_hole\":\n",
" self.debug_draw.draw_circle(\n",
" pos, planet_def[\"radius\"] * 5, color=(1, 1, 1), line_width=0.1\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "357866b3-876e-421f-8d2a-77d6697551d3",
"metadata": {},
"source": [
"# Controlls\n",
"* To play this game, use 'w','a','s','d' on your keyboard to steer the rocket\n",
"* try to land on the other planet\n",
"* avoid the black hole\n",
"* Use the mouse-wheel to zoom in/out, a\n",
"* Click and drag in the empty space to translate the view."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7bab75b7-cec1-4348-b95d-9ffd282ded5c",
"metadata": {},
"outputs": [],
"source": [
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"s = JupyterAsyncGui.Settings()\n",
"s.resolution = [1000,1000]\n",
"s.scale = 3\n",
"tb = b2d.testbed.run(Rocket, backend=JupyterAsyncGui, gui_settings=s);"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "674c57c8-b5b1-45a9-b75e-5ddc487f7d9b",
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,128 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "39a80aae-a990-4ed8-b880-3db2e7f70f16",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.2')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9d9f8d68-0f3b-49c1-9512-e3e8344e7342",
"metadata": {},
"outputs": [],
"source": [
"from b2d.testbed import TestbedBase\n",
"import random\n",
"import numpy\n",
"import b2d\n",
"\n",
"\n",
"class GaussMachine(TestbedBase):\n",
"\n",
" name = \"Gauss Machine\"\n",
"\n",
" def __init__(self, settings=None):\n",
" super(GaussMachine, self).__init__(settings=settings)\n",
"\n",
" self.box_shape = 30, 20\n",
" box_shape = self.box_shape\n",
"\n",
" # outer box\n",
" verts = numpy.array(\n",
" [(0, box_shape[1]), (0, 0), (box_shape[0], 0), (box_shape[0], box_shape[1])]\n",
" )\n",
" shape = b2d.chain_shape(vertices=numpy.flip(verts, axis=0))\n",
" box = self.world.create_static_body(position=(0, 0), shape=shape)\n",
"\n",
" # \"bins\"\n",
" bin_height = box_shape[1] / 3\n",
" bin_width = 1\n",
" for x in range(0, box_shape[0], bin_width):\n",
" box = self.world.create_static_body(\n",
" position=(0, 0), shape=b2d.two_sided_edge_shape((x, 0), (x, bin_height))\n",
" )\n",
"\n",
" # reflectors\n",
" ref_start_y = int(bin_height + box_shape[1] / 10.0)\n",
" ref_stop_y = int(box_shape[1] * 0.9)\n",
" for x in range(0, box_shape[0] + 1):\n",
"\n",
" for y in range(ref_start_y, ref_stop_y):\n",
" s = [0.5, 0][y % 2 == 0]\n",
" shape = b2d.circle_shape(radius=0.3)\n",
" box = self.world.create_static_body(position=(x + s, y), shape=shape)\n",
"\n",
" # particle system\n",
" pdef = b2d.particle_system_def(\n",
" viscous_strength=0.9,\n",
" spring_strength=0.0,\n",
" damping_strength=100.5,\n",
" pressure_strength=1.0,\n",
" color_mixing_strength=0.05,\n",
" density=2,\n",
" )\n",
"\n",
" psystem = self.world.create_particle_system(pdef)\n",
" psystem.radius = 0.1\n",
" psystem.damping = 0.5\n",
"\n",
" # linear emitter\n",
" emitter_pos = (self.box_shape[0] / 2, self.box_shape[1] + 10)\n",
" emitter_def = b2d.RandomizedLinearEmitterDef()\n",
" emitter_def.emite_rate = 400\n",
" emitter_def.lifetime = 25\n",
" emitter_def.size = (10, 1)\n",
" emitter_def.transform = b2d.Transform(emitter_pos, b2d.Rot(0))\n",
"\n",
" self.emitter = b2d.RandomizedLinearEmitter(psystem, emitter_def)\n",
"\n",
" def pre_step(self, dt):\n",
" self.emitter.step(dt)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "51e5df1b-f5e6-486a-a6c0-173597198e5d",
"metadata": {},
"outputs": [],
"source": [
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"s = JupyterAsyncGui.Settings()\n",
"s.resolution = [350,400]\n",
"s.scale = 11\n",
"tb = b2d.testbed.run(GaussMachine, backend=JupyterAsyncGui, gui_settings=s);"
]
}
],
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,130 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "82ae535a-a041-40f0-8c40-e689b894b0bc",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"if \"pyodide\" in sys.modules:\n",
" import piplite\n",
" await piplite.install('pyb2d-jupyterlite-backend>=0.4.0')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "7381ff66-7924-4216-b141-8f7b15ed038a",
"metadata": {},
"outputs": [],
"source": [
"from b2d.testbed import TestbedBase\n",
"import b2d\n",
"\n",
"\n",
"class NewtonsCradle(TestbedBase):\n",
"\n",
" name = \"newton's cradle\"\n",
"\n",
" def __init__(self, settings=None):\n",
" super(NewtonsCradle, self).__init__(settings=settings)\n",
"\n",
" # radius of the circles\n",
" r = 1.0\n",
" # length of the rope\n",
" l = 10.0\n",
" # how many balls\n",
" n = 10\n",
"\n",
" offset = (l + r, 2 * r)\n",
" dynamic_circles = []\n",
" static_bodies = []\n",
" for i in range(n):\n",
" if i + 1 == n:\n",
" position = (offset[0] + i * 2 * r + l, offset[1] + l)\n",
" else:\n",
" position = (offset[0] + i * 2 * r, offset[1])\n",
"\n",
" circle = self.world.create_dynamic_body(\n",
" position=position,\n",
" fixtures=b2d.fixture_def(\n",
" shape=b2d.circle_shape(radius=r * 0.90),\n",
" density=1.0,\n",
" restitution=1.0,\n",
" friction=0.0,\n",
" ),\n",
" linear_damping=0.01,\n",
" angular_damping=1.0,\n",
" fixed_rotation=True,\n",
" )\n",
" dynamic_circles.append(circle)\n",
"\n",
" static_body = self.world.create_static_body(\n",
" position=(offset[0] + i * 2 * r, offset[1] + l)\n",
" )\n",
"\n",
" self.world.create_distance_joint(\n",
" static_body,\n",
" circle,\n",
" local_anchor_a=(0, 0),\n",
" local_anchor_b=(0, 0),\n",
" max_length=l,\n",
" stiffness=0,\n",
" )\n",
"\n",
" static_bodies.append(static_body)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "6f694d32-8b23-40cf-91c3-0edd6abb658d",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b24ad88f6cfd4db19fc3145000e79635",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Output()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from pyb2d_jupyterlite_backend.async_jupyter_gui import JupyterAsyncGui\n",
"s = JupyterAsyncGui.Settings()\n",
"s.resolution = [1000,300]\n",
"b2d.testbed.run(NewtonsCradle, backend=JupyterAsyncGui, gui_settings=s);"
]
}
],
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1 @@
{"metadata":{"language_info":{"codemirror_mode":{"name":"python","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.8"},"kernelspec":{"name":"python","display_name":"Pyolite","language":"python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# JupyterLab Renderers","metadata":{}},{"cell_type":"markdown","source":"## FASTA","metadata":{}},{"cell_type":"code","source":"def Fasta(data=''):\n bundle = {}\n bundle['application/vnd.fasta.fasta'] = data\n bundle['text/plain'] = data\n display(bundle, raw=True)\n\nFasta(\"\"\">SEQUENCE_1\nMTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKADRLAAEG\nLVSVKVSDDFTIAAMRPSYLSYEDLDMTFVENEYKALVAELEKENEERRRLKDPNKPEHK\nIPQFASRKQLSDAILKEAEEKIKEELKAQGKPEKIWDNIIPGKMNSFIADNSQLDSKLTL\nMGQFYVMDDKKTVEQVIAEKEKEFGGKIKIVEFICFEVGEGLEKKTEDFAAEVAAQL\n>SEQUENCE_2\nSATVSEINSETDFVAKNDQFIALTKDTTAHIQSNSLQSVEELHSSTINGVKFEEYLKSQI\nATIGENLVVRRFATLKAGANGVVNGYIHTNGRVGVVIAAACDSAEVASKSRDLLRQICMH\"\"\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## GeoJSON","metadata":{}},{"cell_type":"code","source":"def GeoJSON(data):\n bundle = {}\n bundle['application/geo+json'] = data\n bundle['text/plain'] = data\n display(bundle, raw=True)\n \nGeoJSON({\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [125.6, 10.1]\n },\n \"properties\": {\n \"name\": \"Dinagat Islands\"\n }\n})","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}

721
content/python.ipynb Normal file
View File

@ -0,0 +1,721 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"# A Python kernel backed by Pyodide\n",
"\n",
"![](https://raw.githubusercontent.com/pyodide/pyodide/master/docs/_static/img/pyodide-logo.png)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import pyodide_kernel\n",
"pyodide_kernel.__version__"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Simple code execution"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"a = 3"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"a"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"b = 89\n",
"\n",
"def sq(x):\n",
" return x * x\n",
"\n",
"sq(b)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"print"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"# Redirected streams"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import sys\n",
"\n",
"print(\"Error !!\", file=sys.stderr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Error handling"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true,
"trusted": true
},
"outputs": [],
"source": [
"\"Hello\"\n",
"\n",
"def dummy_function():\n",
" import missing_module"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"dummy_function()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Code completion"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### press `tab` to see what is available in `sys` module"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from sys import "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Code inspection"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### using the question mark"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"?print"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### by pressing `shift+tab`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"print("
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Input support"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"name = await input('Enter your name: ')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"'Hello, ' + name"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Rich representation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import display, Markdown, HTML, JSON, Latex"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"## HTML"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"print('Before display')\n",
"\n",
"s = '<h1>HTML Title</h1>'\n",
"display(HTML(s))\n",
"\n",
"print('After display')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Markdown"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"Markdown('''\n",
"# Title\n",
"\n",
"**in bold**\n",
"\n",
"~~Strikthrough~~\n",
"''')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pandas DataFrame"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"from string import ascii_uppercase as letters\n",
"from IPython.display import display\n",
"\n",
"df = pd.DataFrame(np.random.randint(0, 100, size=(100, len(letters))), columns=list(letters))\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Show the same DataFrame "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## IPython.display module"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import clear_output, display, update_display\n",
"from asyncio import sleep"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Update display"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class Square:\n",
" color = 'PeachPuff'\n",
" def _repr_html_(self):\n",
" return '''\n",
" <div style=\"background: %s; width: 200px; height: 100px; border-radius: 10px;\">\n",
" </div>''' % self.color\n",
"square = Square()\n",
"\n",
"display(square, display_id='some-square')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"square.color = 'OliveDrab'\n",
"update_display(square, display_id='some-square')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Clear output"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"print(\"hello\")\n",
"await sleep(3)\n",
"clear_output() # will flicker when replacing \"hello\" with \"goodbye\"\n",
"print(\"goodbye\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"print(\"hello\")\n",
"await sleep(3)\n",
"clear_output(wait=True) # prevents flickering\n",
"print(\"goodbye\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Display classes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import HTML\n",
"HTML('''\n",
" <div style=\"background: aliceblue; width: 200px; height: 100px; border-radius: 10px;\">\n",
" </div>''')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import Math\n",
"Math(r'F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import Latex\n",
"Latex(r\"\"\"\\begin{eqnarray}\n",
"\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\\n",
"\\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\\n",
"\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\\n",
"\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 \n",
"\\end{eqnarray}\"\"\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import ProgressBar\n",
"\n",
"for i in ProgressBar(10):\n",
" await sleep(0.1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import JSON\n",
"JSON(['foo', {'bar': ('baz', None, 1.0, 2)}], metadata={}, expanded=True, root='test')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from IPython.display import GeoJSON\n",
"GeoJSON(\n",
" data={\n",
" \"type\": \"Feature\",\n",
" \"geometry\": {\n",
" \"type\": \"Point\",\n",
" \"coordinates\": [11.8, -45.04]\n",
" }\n",
" }, url_template=\"http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png\",\n",
" layer_options={\n",
" \"basemap_id\": \"celestia_mars-shaded-16k_global\",\n",
" \"attribution\" : \"Celestia/praesepe\",\n",
" \"tms\": True,\n",
" \"minZoom\" : 0,\n",
" \"maxZoom\" : 5\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Network requests and JSON"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import json\n",
"from js import fetch"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"res = await fetch('https://httpbin.org/get')\n",
"text = await res.text()\n",
"obj = json.loads(text) \n",
"JSON(obj)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sympy"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from sympy import Integral, sqrt, symbols, init_printing\n",
"\n",
"init_printing()\n",
"\n",
"x = symbols('x')\n",
"\n",
"Integral(sqrt(1 / x), x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Magics"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import os\n",
"os.listdir()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%cd /home"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%pwd"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"current_path = %pwd\n",
"print(current_path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%%writefile test.txt\n",
"\n",
"This will create a new file. \n",
"With the text that you see here."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%history"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"import time"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"%%timeit \n",
"\n",
"time.sleep(0.1)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (Pyodide)",
"language": "python",
"name": "python"
},
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,29 @@
{
"metadata": {
"orig_nbformat": 4,
"language_info": {
"file_extension": ".lua",
"mimetype": "text/x-luasrc",
"name": "lua",
"version": "14.0.0"
},
"kernelspec": {
"name": "Lua",
"display_name": "Lua",
"language": "lua"
}
},
"nbformat_minor": 4,
"nbformat": 4,
"cells": [
{
"cell_type": "code",
"source": "canvas = ilua.canvas.canvas()\nilua.display.display(canvas)\ncanvas:cache()\nfor var=1,100 do\n canvas:begin_path()\n canvas:move_to(canvas:rand_coord())\n for s=1,10 do\n canvas:line_to(canvas:rand_coord())\n end\n canvas.fill_style = canvas:rand_color()\n canvas:fill()\nend\ncanvas:flush()",
"metadata": {
"trusted": true
},
"execution_count": null,
"outputs": []
}
]
}

View File

@ -0,0 +1,92 @@
{
"metadata":{
"orig_nbformat":4,
"kernelspec":{
"name":"Lua",
"display_name":"Lua",
"language":"lua"
},
"language_info":{
"file_extension":".lua",
"mimetype":"text/x-luasrc",
"name":"lua",
"version":"14.0.0"
}
},
"nbformat_minor":5,
"nbformat":4,
"cells":[
{
"cell_type":"code",
"source":"math = require(\"math\")\n\n-- the game of life class itself\nGameOfLife = {}\nGameOfLife.__index = GameOfLife\nfunction GameOfLife:Create(grid_size)\n local this =\n {\n grid_size = grid_size or {10,10},\n grid = {}\n }\n setmetatable(this, GameOfLife)\n this.size = this.grid_size[1] * this.grid_size[2]\n for i=1,this.size do\n this.grid[i] = 0\n end\n return this\nend",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
],
"id":"61dc1d13-5546-477d-a162-e18ec564e3ee"
},
{
"cell_type":"code",
"source":"-- member function to initalize with some random values\nfunction GameOfLife:init_random(p)\n for i=1,self.size do\n self.grid[i] = (math.random() < p) and 1 or 0\n end\nend",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
],
"id":"72da5a15-dd9d-4a62-bfa3-5a3ec457c5f4"
},
{
"cell_type":"code",
"source":"-- helper function to convert a coordinate {x,y} into a \n-- scalar offset\nfunction GameOfLife:to_offset(coord)\n return (coord[1]-1) * self.grid_size[2] + (coord[2] -1) + 1\nend\n-- helper function to access the value of the grid at a coordinate {x,y}\nfunction GameOfLife:at(coord)\n return self.grid[self:to_offset(coord)]\nend",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
],
"id":"0b341677-64f2-4ef3-8ea4-a8e2eb275df2"
},
{
"cell_type":"code",
"source":"-- the function to do a step\nfunction GameOfLife:step()\n new_grid = {}\n \n for x=1,self.grid_size[1] do\n for y=1, self.grid_size[2] do\n \n local c = 0\n for xx=-1,1 do\n for yy=-1,1 do\n nx = x + xx\n ny = y + yy\n if nx >=1 and ny>=1 and nx <=self.grid_size[1] and ny <=self.grid_size[2] and not (xx==0 and yy ==0) then\n c = c + self:at({nx,ny})\n end\n end\n end\n \n local offset = self:to_offset({x,y})\n local current_state = self:at({x,y})\n \n new_grid[offset] = 0\n if current_state == 0 then\n if c == 3 then\n new_grid[offset] = 1\n end\n else\n if c==2 or c==3 then\n new_grid[offset] = 1\n else\n new_grid[offset] = 0\n end\n end\n-- \n end\n end\n self.grid = new_grid\nend",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
],
"id":"7958dd53-006c-480d-a4ad-9f04b147fd29"
},
{
"cell_type":"code",
"source":"-- helper function to draw the grid as string\nfunction GameOfLife:__tostring()\n s = \"*\"\n for y=1, self.grid_size[2] do\n s = s .. \"--\"\n end\n s = s .. \"*\\n\"\n for x=1,self.grid_size[1] do\n s = s .. \"|\"\n for y=1, self.grid_size[2] do\n local state = self:at({x,y})\n if state == 0 then\n ss = \" \"\n else\n ss = \"O\"\n end\n s = s .. ss .. \" \"\n end\n s = s .. \"|\\n\"\n end\n s = s .. \"*\"\n for y=1, self.grid_size[2] do\n s = s .. \"--\"\n end\n s = s .. \"*\\n\"\n return s\nend",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
],
"id":"884414f6-8bc9-4719-9671-ef3be310356b"
},
{
"cell_type":"code",
"source":"-- initalize the game of life\ngrid_size = {20,20}\ngame_of_life = GameOfLife:Create(grid_size)\ngame_of_life:init_random(0.5)\n\n-- a tiny gui\nfunction speed_to_interval(speed)\n return 1.0 / speed\nend\n\nspeed = 0.001\n\nhbox = ilua.widgets.hbox()\n\nplay = ilua.widgets.play({interval=speed_to_interval(speed), max=1000000})\noutput = ilua.widgets.output()\nstep_label = ilua.widgets.label({value=\"Step: \"..tostring(play.value)})\nspeed_label = ilua.widgets.label({value=\"Speed: \"..tostring(speed)})\nspeed_slider = ilua.widgets.slider({min=0.001, max=0.5, step=0.01})\n\nhbox:add(play,step_label,speed_label)\n\nspeed_slider:register_observer(function(value)\n output:captured(function()\n speed = value\n play.interval = speed_to_interval(speed)\n speed_label.value = \"Speed: \" .. tostring(speed)\n end)\nend)\n\nplay:register_observer(function(value)\n if value <= 0.1 then\n game_of_life:init_random(0.24)\n end\n -- use output widget to caputre prints \n output:captured(function()\n ilua.display.clear_output(false)\n step_label.value = \"STEP \"..tostring(play.value)\n game_of_life:step()\n print(tostring(game_of_life))\n end)\nend)\nilua.display.display(hbox,speed_slider, output)",
"metadata":{
"trusted":true
},
"execution_count":null,
"outputs":[
],
"id":"40cabf23-7eef-4501-badd-99c1a68c5ced"
}
]
}

View File

@ -0,0 +1,632 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "6d755081-7f9f-4c6a-93e5-a28c8627a0ec",
"metadata": {},
"source": [
"Button\n",
"======="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "be69e205-0c56-44b7-926b-5482d5300a38",
"metadata": {},
"outputs": [],
"source": [
"button = ilua.widgets.button({description=\"hello\"})\n",
"output = ilua.widgets.output()\n",
"ilua.display.display(button,output)\n",
"button:on_click(function()\n",
" output:captured(function()\n",
" print(\"clicked\")\n",
" end)\n",
"end)"
]
},
{
"cell_type": "markdown",
"id": "d11b0def-5115-4369-9972-4766802c846f",
"metadata": {
"tags": []
},
"source": [
"Box Layout\n",
"=========="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5d044224-ac2e-4722-b3fb-6d75b13ec366",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"slider_a = ilua.widgets.slider({min=1, max=2, step=0.1})\n",
"slider_b = ilua.widgets.slider({min=10, max=20, step=1})\n",
"hbox = ilua.widgets.hbox()\n",
"output = ilua.widgets.output()\n",
"hbox:add(slider_a, slider_b)\n",
"ilua.display.display(hbox,output)\n",
"\n",
"slider_a:register_observer(function(value)\n",
" output:captured(function()\n",
" io.write(\"f(x) = x**2; f(\", value ,\")=\", value*value,\"\\n\")\n",
" end)\n",
"end)\n",
"slider_b:register_observer(function(value)\n",
" output:captured(function()\n",
" io.write(\"f(x) = x**3; f(\", value ,\")=\", value*value*value,\"\\n\")\n",
" end)\n",
"end)"
]
},
{
"cell_type": "markdown",
"id": "98e79948-9aeb-4c31-a7b9-3c6bce6c026f",
"metadata": {},
"source": [
"Accordion\n",
"================"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b755c37d-602a-4b46-97ee-8e044f2f2314",
"metadata": {},
"outputs": [],
"source": [
"output = ilua.widgets.output()\n",
"button = ilua.widgets.button({description=\"a button\"})\n",
"button:on_click(function() \n",
" output:captured(function()\n",
" print(\"clicked button\")\n",
" end)\n",
"end)\n",
"slider = ilua.widgets.slider()\n",
"color_picker = ilua.widgets.color_picker()\n",
"audio = ilua.widgets.audio()\n",
"accordion = ilua.widgets.accordion()\n",
"accordion:add(slider,button,color_picker,audio)\n",
"accordion:set_title(1,\"the slider\")\n",
"accordion:set_title(2,\"the button\")\n",
"accordion:set_title(3,\"the color_picker\")\n",
"accordion:set_title(4,\"the audio\")\n",
"ilua.display.display(accordion, output)\n",
"\n",
"slider:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"slider value\", value)\n",
" end)\n",
"end)\n",
"\n",
"color_picker:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"color_picker value\", value)\n",
" end)\n",
"end)"
]
},
{
"cell_type": "markdown",
"id": "097d19f7-a0c9-48a9-8eff-6e3e06780c88",
"metadata": {
"tags": []
},
"source": [
"Dropdown\n",
"========="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "95e12c50-4e77-457c-b2c2-6d20421a3bea",
"metadata": {},
"outputs": [],
"source": [
"labels = {\"aaa\", \"bb\",\"cc\"}\n",
"dropdown = ilua.widgets.dropdown({_options_labels= labels})\n",
"output = ilua.widgets.output()\n",
"dropdown:register_observer(function(index)\n",
" output:captured(function()\n",
" print(labels[index])\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(dropdown, output)"
]
},
{
"cell_type": "markdown",
"id": "ca362331-bd0c-4203-9a6f-dc937d309297",
"metadata": {},
"source": [
"Html\n",
"======="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "abc66753-53ba-4361-96a6-48cd9460c8e3",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"src = [[\n",
"<!DOCTYPE html>\n",
"<html>\n",
" <head>\n",
" </head>\n",
" <body>\n",
" <h1>My First Page</h1>\n",
" <p>This is my first page.</p>\n",
" <h2>A secondary header.</h2>\n",
" <p>Some more text.</p>\n",
" </body>\n",
"</html>\n",
"]]\n",
"html = ilua.widgets.html({value=src})\n",
"ilua.display.display(html)"
]
},
{
"cell_type": "markdown",
"id": "e8eeacfe-350a-4ecb-81a9-c8091af3c22e",
"metadata": {
"tags": []
},
"source": [
"numeral\n",
"========"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9c177cfe-2613-43a3-a217-d93bc257420e",
"metadata": {},
"outputs": [],
"source": [
"numeral = ilua.widgets.numeral()\n",
"output = ilua.widgets.output()\n",
"numeral:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"value\", value)\n",
" end)\n",
"end)\n",
"ilua.display.display(numeral, output)"
]
},
{
"cell_type": "markdown",
"id": "9fede355-2e4f-48c9-b39b-1886e060ce8b",
"metadata": {},
"source": [
"password\n",
"========"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "455996cf-9b63-4d50-869a-0f479ab3daf4",
"metadata": {},
"outputs": [],
"source": [
"password = ilua.widgets.password()\n",
"output = ilua.widgets.output()\n",
"password:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"value\", value)\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(password, output)"
]
},
{
"cell_type": "markdown",
"id": "6306ce8e-37d3-4dbc-a8cf-955b2dfe684c",
"metadata": {},
"source": [
"play\n",
"====="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "986147ab-c9de-4ad9-b8be-f65260dd815d",
"metadata": {},
"outputs": [],
"source": [
"play = ilua.widgets.play({interval=1000})\n",
"output = ilua.widgets.output()\n",
"play:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"value\", value)\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(play, output)"
]
},
{
"cell_type": "markdown",
"id": "4e03ccf2-3a10-40d6-8273-168a91f3d9a7",
"metadata": {},
"source": [
"progress\n",
"========="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a4f194ee-0995-44f3-8636-b629bd5b65ba",
"metadata": {},
"outputs": [],
"source": [
"progress = ilua.widgets.progress({min=10, max=20})\n",
"play = ilua.widgets.play({min=10, max=20, interval=100})\n",
"play:register_observer(function(value)\n",
" progress.value = value\n",
"end)\n",
"ilua.display.display(play, progress)"
]
},
{
"cell_type": "markdown",
"id": "39714034-99f4-4f36-b50f-33aa3f71d2a6",
"metadata": {},
"source": [
"Selection Slider\n",
"================="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7f6aab9e-b3ce-4df9-83a6-94eb725aceb0",
"metadata": {},
"outputs": [],
"source": [
"labels = {\"aaa\", \"bb\",\"cc\"}\n",
"selectionslider = ilua.widgets.selectionslider({_options_labels = labels})\n",
"output = ilua.widgets.output()\n",
"selectionslider:register_observer(function(index)\n",
" output:captured(function()\n",
" print(labels[index])\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(selectionslider, output)"
]
},
{
"cell_type": "markdown",
"id": "45d72396-3fcc-421e-865e-487d93b333b8",
"metadata": {},
"source": [
"Tab\n",
"======"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6d0684e8-62a2-4483-995a-70d7cc2783ac",
"metadata": {},
"outputs": [],
"source": [
"\n",
"\n",
"slider_a = ilua.widgets.slider()\n",
"slider_b = ilua.widgets.slider()\n",
"\n",
"titles = {\"aaa\", \"bb\",\"cc\"}\n",
"tab = ilua.widgets.tab({_titles = titles})\n",
"tab:add(slider_a,slider_b)\n",
"output = ilua.widgets.output()\n",
"\n",
"tab:register_observer(function(index)\n",
" -- use output widget to caputre prints \n",
" output:captured(function()\n",
" print(titles[index])\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(tab,output)"
]
},
{
"cell_type": "markdown",
"id": "7f9f85de-a5b8-4e60-9eff-33b25d819ec9",
"metadata": {},
"source": [
"Text\n",
"====="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "893e92ad-eff2-4adb-ba82-71a9ed2cfe9e",
"metadata": {},
"outputs": [],
"source": [
"text = ilua.widgets.text()\n",
"output = ilua.widgets.output()\n",
"text:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"value\", value)\n",
" end)\n",
"end)\n",
"\n",
"text:on_submit(function()\n",
" output:captured(function()\n",
" print(\"on_submit\")\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(text, output)"
]
},
{
"cell_type": "markdown",
"id": "94572d62-12ea-4026-a531-d0e7bc5b20b9",
"metadata": {},
"source": [
"TextArea\n",
"========="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1e76b56f-f087-49f8-a50e-eb794060c63c",
"metadata": {},
"outputs": [],
"source": [
"textarea = ilua.widgets.textarea({continuous_update=false})\n",
"output = ilua.widgets.output()\n",
"textarea:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"value\", value)\n",
" end)\n",
"end)\n",
"ilua.display.display(textarea, output)"
]
},
{
"cell_type": "markdown",
"id": "68011d67-ac8c-43ff-bae9-4caf95273f98",
"metadata": {},
"source": [
"Toggle Button\n",
"========="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cf780275-b2de-48d4-bb2e-3f38e8c45bcd",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"togglebutton = ilua.widgets.togglebutton({\n",
" icon=\"plus\",\n",
" button_style=\"\"\n",
"})\n",
"output = ilua.widgets.output()\n",
"togglebutton:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"value\", value)\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(togglebutton, output)"
]
},
{
"cell_type": "markdown",
"id": "1bc5c504-cf9c-432f-a91c-2497910d787b",
"metadata": {},
"source": [
"ToggleButtons\n",
"========="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f764f285-d71f-4c93-92b4-923484846b0c",
"metadata": {},
"outputs": [],
"source": [
"togglebuttons = ilua.widgets.togglebuttons()\n",
"togglebuttons._options_labels = {\"1\", \"2\",\"3\"}\n",
"output = ilua.widgets.output()\n",
"togglebuttons:register_observer(function(value)\n",
" output:captured(function()\n",
" print(\"value\", value)\n",
" end)\n",
"end)\n",
"\n",
"ilua.display.display(togglebuttons, output)"
]
},
{
"cell_type": "markdown",
"id": "55447db2-bab0-4282-9a89-f6b9f8fd9e30",
"metadata": {},
"source": [
"Image\n",
"========"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d21c5e4b-1d27-44e9-9966-0da4ef55f651",
"metadata": {},
"outputs": [],
"source": [
"io = require(\"io\")\n",
"file = io.open(\"marie.png\", \"r\")\n",
"content = file:read(\"*all\")\n",
"io.close(file)\n",
"\n",
"image = ilua.widgets.image()\n",
"image.value = content\n",
"ilua.display.display(image)"
]
},
{
"cell_type": "markdown",
"id": "ee4e079c-0101-49a9-94f6-2d7e73ad3f59",
"metadata": {
"tags": []
},
"source": [
"Video\n",
"========"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "654c050a-3cff-48d2-b7a1-d8f6acfe042a",
"metadata": {},
"outputs": [],
"source": [
"io = require(\"io\")\n",
"file = io.open(\"Big.Buck.Bunny.mp4\", \"r\")\n",
"content = file:read(\"*all\")\n",
"io.close(file)\n",
"\n",
"video = ilua.widgets.video({loop=false})\n",
"video.value = content\n",
"ilua.display.display(video)"
]
},
{
"cell_type": "markdown",
"id": "829cf76c-238d-456f-a5b9-51f3a526f45c",
"metadata": {},
"source": [
"Audio\n",
"======"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "43922e68-ee53-40bd-bf2c-8dcc810bdb6a",
"metadata": {},
"outputs": [],
"source": [
"io = require(\"io\")\n",
"file = io.open(\"hehe.flac\", \"r\")\n",
"content = file:read(\"*all\")\n",
"io.close(file)\n",
"\n",
"audio = ilua.widgets.audio({loop=false})\n",
"audio.value = content\n",
"ilua.display.display(audio)"
]
},
{
"cell_type": "markdown",
"id": "2aee848b-a3e6-4ce3-9d2d-8650871bb225",
"metadata": {},
"source": [
"Valid\n",
"======"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ef2ae714-2077-4767-9c24-af821fbc2c9d",
"metadata": {},
"outputs": [],
"source": [
"valid = ilua.widgets.valid()\n",
"valid.value = false\n",
"ilua.display.display(valid)"
]
},
{
"cell_type": "markdown",
"id": "96b64ffe-ac69-4b0e-9299-0a54842a77c1",
"metadata": {},
"source": [
"Link Widgets\n",
"============"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "191675ca-c53e-4c83-a0cf-8dcd78b02fae",
"metadata": {},
"outputs": [],
"source": [
"slider = ilua.widgets.slider()\n",
"numeral = ilua.widgets.numeral()\n",
"\n",
"link = ilua.widgets.link(slider, \"value\", numeral, \"value\")\n",
"ilua.display.display(link, slider, numeral)"
]
},
{
"cell_type": "markdown",
"id": "3d54b0cc-7f2f-4ad7-92a8-9f61abe989f9",
"metadata": {},
"source": [
"Directional Link\n",
"==================="
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21499154-6da9-4a4a-a6ce-7637916d26c6",
"metadata": {},
"outputs": [],
"source": [
"slider = ilua.widgets.slider()\n",
"numeral = ilua.widgets.numeral()\n",
"\n",
"link = ilua.widgets.directional_link(slider, \"value\", numeral, \"value\")\n",
"ilua.display.display(link, slider, numeral)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Lua 0.2 (XLua)",
"language": "lua",
"name": "xlua"
},
"language_info": {
"file_extension": ".lua",
"mimetype": "text/x-luasrc",
"name": "lua",
"version": "14.0.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

File diff suppressed because one or more lines are too long

11
repl/jupyter-lite.json Normal file
View File

@ -0,0 +1,11 @@
{
"jupyter-lite-schema-version": 0,
"jupyter-config-data": {
"disabledExtensions": [
"@jupyterlab/drawio-extension",
"jupyterlab-kernel-spy",
"jupyterlab-tour"
]
}
}

46
requirements.txt Normal file
View File

@ -0,0 +1,46 @@
# Core modules (mandatory)
jupyterlite-core==0.1.0
jupyterlab~=3.5.1
# Python kernel (optional)
jupyterlite-pyodide-kernel==0.0.6
# JavaScript kernel (optional)
jupyterlite-javascript-kernel==0.1.0b21
# Language support (optional)
jupyterlab-language-pack-fr-FR
jupyterlab-language-pack-zh-CN
# SQLite kernel (optional)
jupyterlite-xeus-sqlite==0.2.1
# P5 kernel (optional)
jupyterlite-p5-kernel==0.1.0
# Lua kernel (optional)
jupyterlite-xeus-lua==0.3.1
# JupyterLab: Fasta file renderer (optional)
jupyterlab-fasta>=3,<4
# JupyterLab: Geojson file renderer (optional)
jupyterlab-geojson>=3,<4
# JupyterLab: guided tour (optional)
jupyterlab-tour
# JupyterLab: dark theme
jupyterlab-night
# JupyterLab: Miami nights theme (optional)
jupyterlab_miami_nights
# Python: ipywidget library for Jupyter notebooks (optional)
ipywidgets>=8.0.0,<9
# Python: ipyevents library for Jupyter notebooks (optional)
ipyevents>=2.0.1
# Python: interative Matplotlib library for Jupyter notebooks (optional)
ipympl>=0.8.2
# Python: ipycanvas library for Jupyter notebooks (optional)
ipycanvas>=0.9.1
# Python: ipyleaflet library for Jupyter notebooks (optional)
ipyleaflet
# Python: plotting libraries (optional)
plotly>=5,<6
bqplot