Skip to content

Commit 549101f

Browse files
Merge pull request #44 from GLVis/anywidget
Rewrite to use anywidget
2 parents cd40a84 + f3d4b06 commit 549101f

29 files changed

Lines changed: 310 additions & 3764 deletions

.binder/postBuild

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
11
# install this
22
pip install .
3-
4-
# install jupyter-lab extension
5-
jupyter labextension install @jupyter-widgets/jupyterlab-manager --no-build
6-
jupyter labextension install glvis-jupyter

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
BSD 3-Clause License
22

3-
Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC
3+
Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC
44
All rights reserved.
55

66
Redistribution and use in source and binary forms, with or without

MANIFEST.in

Lines changed: 0 additions & 2 deletions
This file was deleted.

README.md

Lines changed: 95 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,197 +1,152 @@
1-
# Interactive GLVis Jupyter Widget
1+
# PyGLVis
22

33
<!-- Badges generated at https://mybinder.readthedocs.io/en/latest/howto/badges.html -->
44
[![badge](examples/basic.svg "Basic GLVis + Jupyter Example")](https://mybinder.org/v2/gh/GLVis/pyglvis/HEAD?filepath=examples%2Fbasic.ipynb)
55
[![badge](examples/plot.svg "Plot grid functions")](https://mybinder.org/v2/gh/GLVis/pyglvis/HEAD?filepath=examples%2Fplot.ipynb)
66
[![badge](examples/ex1.svg "MFEM's Example 1")](https://mybinder.org/v2/gh/GLVis/pyglvis/HEAD?filepath=examples%2Fex1.ipynb)
77
[![badge](examples/ex9.svg "MFEM's Example 9")](https://mybinder.org/v2/gh/GLVis/pyglvis/HEAD?filepath=examples%2Fex9.ipynb)
88

9-
This repository contains a [Jupyter](https://jupyter.org/) widget for the [GLVis](https://glvis.org/) finite element
10-
visualization tool based on the [glvis-js](https://github.com/GLVis/glvis-js) JavaScript/WebAssembly library.
9+
PyGLVis is an interactive [Jupyter](https://jupyter.org/) widget for visualizing finite element meshes and functions, built on-top of the [GLVis](https://glvis.org/) library.
1110

12-
## Usage
11+
## 📦 Installation
1312

14-
```python
15-
from glvis import glvis
13+
The GLVis Jupyter widget is installed using `pip`. To install the latest version from the repository:
1614

17-
glvis(data[, width=640, height=480])
15+
```bash
16+
git clone https://github.com/GLVis/pyglvis.git
17+
cd pyglvis
18+
pip install .
19+
```
1820

19-
# or assign if you want to update later
20-
g = glvis(data)
21-
# run a cell with `g` to show it
22-
g
21+
Or, install directly from PyPi,
22+
```bash
23+
pip install glvis
2324
```
2425

25-
The `data` object and be one of:
26+
PyGLVis requires the Python wrapper for MFEM, [PyMFEM](https://github.com/mfem/pymfem), which can be installed with
27+
```bash
28+
pip install mfem
29+
```
2630

27-
- a `str`, in the format of `*.saved` files
28-
- a `Mesh`, defined in [PyMFEM](https://github.com/mfem/pymfem)
29-
- a `(Mesh, GridFunction)` tuple, defined in [PyMFEM](https://github.com/mfem/pymfem)
3031

31-
[PyMFEM](https://github.com/mfem/pymfem) can be installed with `pip install mfem --no-binary mfem`.
3232

33+
## 🚀 Usage
34+
35+
### Basic usage
3336

34-
Once you have a `glvis` object there are a few methods that can used to update the
35-
visualization:
3637
```python
37-
# show a new Mesh/GridFunction, resets keys
38-
g.plot(data)
39-
# show an updated visualization with the same `Mesh` and `GridFunction`
40-
# dimensions, preserves keys
41-
g.update(data)
42-
# change the image size
43-
g.set_size(width, height)
44-
# force the widget to render. if the widget isn't the last statement in a cell it
45-
# will not be shown without this. see ex9.ipynb
46-
g.render()
47-
```
38+
from glvis import glvis
4839

49-
See the [examples](examples/) directory for additional examples. To test those locally, start a Jupyter notebook server with
40+
# Create a `glvis` object
41+
g = glvis(data, width=640, height=480)
5042

43+
# Run a cell with `g` as the last statement to display the widget
44+
g
5145
```
52-
jupyter notebook
53-
```
54-
55-
## Installation
56-
57-
The GLVis Jupyter widget can be simply installed with `pip`:
5846

59-
```
60-
pip install glvis
61-
```
47+
The `data` object can be one of:
6248

63-
It order for the installation to be useful you must enable the extension for one or both
64-
of the [Classic Notebook](https://jupyter-notebook.readthedocs.io/en/stable/) and
65-
[Jupyter Lab](https://jupyterlab.readthedocs.io/en/stable/), see the next two sections:
49+
- `Mesh`, defined in [PyMFEM](https://github.com/mfem/pymfem)
50+
- `(Mesh, GridFunction)` tuple, defined in [PyMFEM](https://github.com/mfem/pymfem)
51+
- `str`, in the format of `*.saved` files [used by MFEM and GLVis](https://mfem.org/mesh-format-v1.0/). See [examples/basic.ipynb](examples/basic.ipynb) for an example.
6652

67-
### Jupyter Notebook
53+
### Customization with key commands
6854

69-
To use the widget with the basic Notebook enable it with `jupyter nbextension enable`:
55+
GLVis has many keyboard commands that can be used to customize the visualization.
56+
A few of the most common are listed below. See the [GLVis README](https://github.com/GLVis/glvis?tab=readme-ov-file#key-commands) for a full list.
57+
- `r` - reset the view
58+
- `c` - toggle the colorbar
59+
- `j` - toggle perspective
60+
- `l` - toggle the light
61+
- `g` - toggle the background color (white/black)
62+
- `a` - cycle through bounding box axes states
63+
- `m` - cycle through mesh states
64+
- `p` - cycle through color palettes
65+
- `t` - cycle through materials and lights
66+
- `0` - begin rotating around z-axis
67+
- `.` - pause rotation
68+
- `*`/`/` - zoom in/out
7069

70+
These can be set using the `keys` argument when creating a `glvis` object.
71+
```python
72+
glvis(data, keys='rljgac//0')
7173
```
72-
jupyter nbextension enable --py glvis
73-
```
74-
75-
After enabling the extension you can verify you're good to go with:
74+
This combination of keys would: `r` reset the view, `l` toggle the light, `j` toggle perspective, `g` toggle the background color to black (default is white), `a` show the bounding box, `c` show the colorbar, `//` zoom out twice, and `0` begin rotating around the z-axis:
7675

77-
```
78-
jupyter nbextension list
79-
```
76+
![pyglvis_preset_keys](https://github.com/GLVis/pyglvis/assets/27717785/de0e0a99-72ac-4a88-8369-708515600b09)
8077

81-
The output should be something like:
78+
Alternatively, keys can be typed directly into the widget after it has been created:
8279

83-
```
84-
Known nbextensions:
85-
config dir: path/to/nbconfig
86-
notebook section
87-
glvis-jupyter/extension enabled
88-
- Validating: OK
89-
<possibly a different config dir>
90-
jupyter-js-widgets/extension enabled
91-
- Validating: OK
92-
```
80+
![pyglvis_using_keys](https://github.com/GLVis/pyglvis/assets/27717785/625f4f06-8f99-4390-94d7-4d317fd11e7f)
9381

94-
If `glvis-jupyter` and `jupyter-js-widgets` are not both listed, try the following:
82+
### Other methods
9583

84+
Once you have a `glvis` object there are a few methods that can used to update the
85+
visualization, besides using keys:
86+
```python
87+
# Show a new Mesh/GridFunction, resets keys
88+
g.plot(data)
89+
# Show an updated visualization with the same data, preserving keys
90+
g.update(data)
91+
# Change the image size
92+
g.set_size(width, height)
93+
# Force the widget to render. If the widget isn't the last statement in a cell it
94+
# will not be shown without this. See ex9.ipynb
95+
g.render()
9696
```
97-
jupyter nbextension install --user --py glvis
98-
jupyter nbextension enable --user --py glvis
99-
jupyter nbextension install --user --py widgetsnbextension
100-
jupyter nbextension enable --user --py widgetsnbextension
101-
```
102-
You may also need to run these if you have upgraded to a newer version of the GLVis Jupyter widget.
10397

104-
### Jupyter Lab
105-
106-
[JupyterLab](https://jupyterlab.readthedocs.io) requires another set of install commands:
98+
See the [examples](examples/) directory for additional examples. To test those locally, start a Jupyter lab server with
10799

108100
```
109-
jupyter labextension install @jupyter-widgets/jupyterlab-manager --no-build
110-
jupyter labextension install glvis-jupyter
101+
jupyter lab
111102
```
112103

113-
## Development
114-
115-
Development installation requires `npm`.
104+
## 🐛 Troubleshooting
116105

117-
If you want to test a new version of `glvis`:
106+
This widget was originally developed using the [jupyter widget cookiecutter](https://github.com/jupyter-widgets/widget-cookiecutter); however, [recent changes to the Jupyter ecosystem](https://jupyter-notebook.readthedocs.io/en/latest/migrate_to_notebook7.html#why-a-new-version) have broken a lot of functionality, leading to a rewrite using [anywidget](https://anywidget.dev/). If you encounter any problems, please consider supporting development by opening an [issue](https://github.com/GLVis/pyglvis/issues).
118107

119-
1. Bump the version in _pyglvis/js/package.json_ and _glvis-js/package.json_
120-
2. `npm install path/to/glvis-js`
121108

122109

123-
Each time you update stuff in _pyglvis/js/src_:
110+
## 🤖 Development
124111

125-
1. `npm install`
126-
2. `npx webpack`
127-
128-
129-
Once:
112+
### PyGLVis dependencies
130113

114+
```mermaid
115+
graph TD;
116+
A[mfem] --> B[pymfem];
117+
A --> C[glvis];
118+
C --> D[glvis-js];
119+
Ext1[emscripten] --> D;
120+
D-.-E["glvis-js\n(npm/esm mirror)"]
121+
B & E --> G[pyglvis];
122+
Ext2[jupyter] --> G;
131123
```
132-
git clone https://github.com/glvis/pyglvis.git
133-
cd pyglvis
134-
pip install -e .
135-
```
136124

137-
### Developing in Jupyter Notebook
125+
`pyglvis` is most directly depednent on `PyMFEM` and `glvis-js`. [PyMFEM](https://github.com/mfem/pymfem) is a Python wrapper of the finite element library, `MFEM`, while `glvis-js` is a JavaScript/WebAssembly port of `glvis`.
126+
127+
`glvis-js` is hosted on [github](https://github.com/glvis/glvis-js) and mirrored on [npm](https://www.npmjs.com/package/glvis). [esm.sh](https://esm.sh/glvis) allows `pyglvis` to pull the latest version of `glvis-js` directly from npm. This can be seen in the first line of [glvis/widget.js](glvis/widget.js):
138128

139129
```
140-
jupyter nbextension install --py --symlink --sys-prefix glvis
141-
jupyter nbextension enable --py --sys-prefix glvis
130+
import glvis from "https://esm.sh/glvis";
142131
```
143132

144-
### Developing in Jupyter Lab
133+
You can specify a different version of `glvis-js` by adding `@x.y.z` to the end of this import statement, where `x.y.z` matches a version number available on `npm`, e.g.
145134

146-
```bash
147-
jupyter labextension install @jupyter-widgets/jupyterlab-manager --no-build
148-
# I believe you need node in the path Lab uses for this to work, I see an extension load error
149-
# in a context where I don't have it:
150-
# Failed to load resource: the server responded with a status of 500 (Internal Server Error)
151-
# lab/api/extensions?1610138347763
152-
# Which is just a python stacktrace, ending with:
153-
# raise ValueError(msg)
154-
# ValueError: Please install Node.js and npm before continuing installation.
155-
jupyter labextension link ./js
156135
```
157-
158-
159-
### Troubleshooting
160-
161-
If you run into errors related to node/npm that aren't helpful try:
162-
163-
```bash
164-
cd pyglvis
165-
make clean
166-
cd js
167-
# fix errors in these steps, run `make -C .. clean` each time
168-
npm install
169-
npx webpack
136+
import glvis from "https://esm.sh/glvis@0.6.3";
170137
```
171138

172-
## Releasing
173139

174-
### Releasing a new version of glvis-jupyter on NPM:
140+
### Releasing a new version of glvis on NPM:
175141

176-
- Update the required version of `glvis` in `js/package.json`
142+
To publish a new version of `glvis-js`, follow the instructions on the [repo](https://github.com/GLVis/glvis-js/tree/master).
177143

178-
- Update the version in `js/package.json`
179-
180-
```bash
181-
# clean out the `dist` and `node_modules` directories
182-
git clean -fdx
183-
npm install
184-
npm publish
185-
```
186144

187145
### Releasing a new version of glvis on PyPI:
188146

189-
- Update `glvis/_version.py`
190-
- Set release version
191-
- Update `extension_version` to match `js/package.json`
147+
- Update `__version__` in `glvis/__about__.py`
192148

193149
- `git add` and `git commit` changes
194-
- `glvis/_version.py`, `js/package.json`, and `js/package-lock.js`
195150

196151

197152
You will need [twine](https://pypi.org/project/twine/) to publish to PyPI, install with `pip`.
@@ -202,3 +157,11 @@ twine upload dist/*
202157
git tag -a X.X.X -m 'comment'
203158
git push --tags
204159
```
160+
161+
162+
## 🌐 Links
163+
- MFEM ([website](https://mfem.org/), [github](https://github.com/mfem/mfem))
164+
- PyMFEM ([github](https://github.com/mfem/pymfem), [pypi](https://pypi.org/project/mfem/))
165+
- GLVis ([website](https://glvis.org/), [github](https://github.com/glvis/glvis))
166+
- glvis-js ([github](https://github.com/glvis/glvis-js), [npm](https://www.npmjs.com/package/glvis), [esm](https://esm.sh/glvis))
167+
- pyglvis ([github](https://github.com/GLVis/pyglvis), [pypi]())

examples/basic.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"outputs": [],
3939
"source": [
4040
"# Another vsualization instance of the same stream\n",
41-
"glvis(stream + 'rljg****tttac0', 300, 300)"
41+
"glvis(stream, 300, 300, keys='rljg****tttac0')"
4242
]
4343
}
4444
],

examples/ex1.ipynb

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
"cells": [
33
{
44
"cell_type": "markdown",
5-
"metadata": {},
5+
"metadata": {
6+
"tags": []
7+
},
68
"source": [
79
"## MFEM Example 1\n",
810
"\n",
@@ -39,12 +41,14 @@
3941
{
4042
"cell_type": "code",
4143
"execution_count": null,
42-
"metadata": {},
44+
"metadata": {
45+
"tags": []
46+
},
4347
"outputs": [],
4448
"source": [
4549
"# Requires PyMFEM, see https://github.com/mfem/PyMFEM\n",
4650
"import mfem.ser as mfem\n",
47-
"from glvis import glvis, to_stream"
51+
"from glvis import glvis"
4852
]
4953
},
5054
{
@@ -107,11 +111,14 @@
107111
{
108112
"cell_type": "code",
109113
"execution_count": null,
110-
"metadata": {},
114+
"metadata": {
115+
"tags": []
116+
},
111117
"outputs": [],
112118
"source": [
113119
"# Plot the mesh + solution (all GLVis keys and mouse commands work)\n",
114-
"glvis((mesh, x), 400, 400)"
120+
"g=glvis((mesh, x))\n",
121+
"g"
115122
]
116123
},
117124
{
@@ -131,15 +138,14 @@
131138
"outputs": [],
132139
"source": [
133140
"# Visualization with additional GLVis keys\n",
134-
"g = glvis(to_stream(mesh,x) + 'keys ARjlmcbp*******')\n",
135-
"g.set_size(600, 400)\n",
141+
"g = glvis((mesh,x), keys='ARjlmcbp*******')\n",
136142
"g"
137143
]
138144
}
139145
],
140146
"metadata": {
141147
"kernelspec": {
142-
"display_name": "Python 3",
148+
"display_name": "Python 3 (ipykernel)",
143149
"language": "python",
144150
"name": "python3"
145151
},
@@ -153,7 +159,7 @@
153159
"name": "python",
154160
"nbconvert_exporter": "python",
155161
"pygments_lexer": "ipython3",
156-
"version": "3.9.1"
162+
"version": "3.10.12"
157163
}
158164
},
159165
"nbformat": 4,

0 commit comments

Comments
 (0)