diff --git a/.gitattributes b/.gitattributes
index 24a8e8793..e4a509285 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,3 @@
*.png filter=lfs diff=lfs merge=lfs -text
+*.npy filter=lfs diff=lfs merge=lfs -text
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7c15e3865..fddfae5f4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,7 +17,7 @@ jobs:
docs-build:
name: Docs
- runs-on: ubuntu-latest
+ runs-on: bigmem
strategy:
fail-fast: false
steps:
@@ -48,7 +48,7 @@ jobs:
test-build-full:
name: Test examples, env with notebook and glfw
- runs-on: ubuntu-latest
+ runs-on: bigmem
if: ${{ !github.event.pull_request.draft }}
strategy:
fail-fast: false
@@ -74,7 +74,7 @@ jobs:
- name: Install llvmpipe and lavapipe for offscreen canvas
run: |
sudo apt-get update -y -qq
- sudo apt-get install --no-install-recommends -y libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers git-lfs
+ sudo apt-get install --no-install-recommends -y ffmpeg libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers git-lfs
- name: Install dev dependencies
run: |
python -m pip install --upgrade pip setuptools
@@ -105,7 +105,7 @@ jobs:
test-build-desktop:
name: Test examples, env with only glfw
- runs-on: ubuntu-latest
+ runs-on: bigmem
if: ${{ !github.event.pull_request.draft }}
strategy:
fail-fast: false
diff --git a/.github/workflows/screenshots.yml b/.github/workflows/screenshots.yml
index 40f55d234..d3cdb919b 100644
--- a/.github/workflows/screenshots.yml
+++ b/.github/workflows/screenshots.yml
@@ -13,7 +13,7 @@ on:
jobs:
screenshots:
name: Regenerate
- runs-on: 'ubuntu-latest'
+ runs-on: bigmem
if: ${{ !github.event.pull_request.draft }}
steps:
- name: Install git-lfs
@@ -27,7 +27,7 @@ jobs:
- name: Install llvmpipe and lavapipe for offscreen canvas
run: |
sudo apt-get update -y -qq
- sudo apt-get install --no-install-recommends -y libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers
+ sudo apt-get install --no-install-recommends -y ffmpeg libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers
- name: Install dev dependencies
run: |
python -m pip install --upgrade pip setuptools
@@ -38,6 +38,10 @@ jobs:
- name: Show wgpu backend
run:
python -c "from examples.tests.testutils import wgpu_backend; print(wgpu_backend)"
+ - name: fetch git lfs files
+ run: |
+ git lfs fetch --all
+ git lfs pull
- name: Test examples
env:
PYGFX_EXPECT_LAVAPIPE: true
diff --git a/README.md b/README.md
index 0f9ccf547..eb64f3cc3 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@
[**Installation**](https://github.com/kushalkolar/fastplotlib#installation) |
[**GPU Drivers**](https://github.com/kushalkolar/fastplotlib#graphics-drivers) |
+[**Documentation**](https://github.com/fastplotlib/fastplotlib#documentation) |
[**Examples**](https://github.com/kushalkolar/fastplotlib#examples) |
[**Contributing**](https://github.com/kushalkolar/fastplotlib#heart-contributing)
@@ -35,7 +36,7 @@ Notebooks from talk: https://github.com/fastplotlib/fastplotlib-scipy2023
:heavy_check_mark: `wxPython`
**Notes:**\
-:heavy_check_mark: You can use a non-blocking `glfw` canvas from a notebook, as long as you're working locally or have a way to forward the remote graphical desktop (such as X11 forwarding).\
+:heavy_check_mark: Non-blocking Qt output is supported in ipython and notebooks by using [`%gui qt`](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-gui) before creating plots. This hook only supports pyqt6 at the moment.\
:grey_exclamation: We do not officially support `jupyter notebook` through `jupyter_rfb`, this may change with notebook v7\
:disappointed: [`jupyter_rfb`](https://github.com/vispy/jupyter_rfb) does not work in collab yet, see https://github.com/vispy/jupyter_rfb/pull/77
@@ -167,4 +168,4 @@ WGPU uses Metal instead of Vulkan on Mac. You will need at least Mac OSX 10.13.
We welcome contributions! See the contributing guide: https://github.com/kushalkolar/fastplotlib/blob/main/CONTRIBUTING.md
-You can also take a look at our [**Roadmap for 2023**](https://github.com/kushalkolar/fastplotlib/issues/55) and [**Issues**](https://github.com/kushalkolar/fastplotlib/issues) for ideas on how to contribute!
+You can also take a look at our [**Roadmap for 2024**](https://github.com/kushalkolar/fastplotlib/issues/55) and [**Issues**](https://github.com/kushalkolar/fastplotlib/issues) for ideas on how to contribute!
diff --git a/docs/source/quickstart.ipynb b/docs/source/quickstart.ipynb
index 6a3afec33..0de4667bf 100644
--- a/docs/source/quickstart.ipynb
+++ b/docs/source/quickstart.ipynb
@@ -97,21 +97,7 @@
"id": "be5b408f-dd91-4e36-807a-8c22c8d7d216",
"metadata": {},
"source": [
- "**In live notebooks or desktop applications, you can use the handle on the bottom right corner of the _canvas_ to resize it. You can also pan and zoom using your mouse!**\n",
- "\n",
- "By default the origin is on the bottom left, you can click the flip button to flip the y-axis, or use `plot.camera.world.scale_y *= -1`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "9b4e977e-2a7d-4e2b-aee4-cfc36767b3c6",
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "plot.camera.world.scale_y *= -1"
+ "**In live notebooks or desktop applications, you can use the handle on the bottom right corner of the _canvas_ to resize it. You can also pan and zoom using your mouse!**"
]
},
{
@@ -510,18 +496,6 @@
"plot_rgb.show()"
]
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7e4b5a30-4293-4ae3-87dc-06a1355bb2c7",
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "plot_rgb.camera.world.scale_y *= -1"
- ]
- },
{
"cell_type": "code",
"execution_count": null,
@@ -1361,7 +1335,7 @@
"outputs": [],
"source": [
"# GridPlot of shape 2 x 3 with all controllers synced\n",
- "grid_plot = fpl.GridPlot(shape=(2, 3), controllers=\"sync\")\n",
+ "grid_plot = fpl.GridPlot(shape=(2, 3), controller_ids=\"sync\")\n",
"\n",
"# Make a random image graphic for each subplot\n",
"for subplot in grid_plot:\n",
@@ -1549,7 +1523,7 @@
"# pan-zoom controllers for each view\n",
"# views are synced if they have the \n",
"# same controller ID\n",
- "controllers = [\n",
+ "controller_ids = [\n",
" [0, 3, 1], # id each controller with an integer\n",
" [2, 2, 3]\n",
"]\n",
@@ -1564,7 +1538,7 @@
"# Create the grid plot\n",
"grid_plot = fpl.GridPlot(\n",
" shape=grid_shape,\n",
- " controllers=controllers,\n",
+ " controller_ids=controller_ids,\n",
" names=names,\n",
")\n",
"\n",
@@ -1678,18 +1652,6 @@
"grid_plot[1, 0][\"rand-image\"].vim = 0.1\n",
"grid_plot[1, 0][\"rand-image\"].vmax = 0.3"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8a5753b9-ee71-4ed1-bb0d-52bdb4ea365f",
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "grid_plot[1, 0][\"rand-image\"].type"
- ]
}
],
"metadata": {
diff --git a/examples/desktop/gridplot/gridplot_non_square.py b/examples/desktop/gridplot/gridplot_non_square.py
index a41bcd9f4..fe43a3c04 100644
--- a/examples/desktop/gridplot/gridplot_non_square.py
+++ b/examples/desktop/gridplot/gridplot_non_square.py
@@ -10,7 +10,7 @@
import imageio.v3 as iio
-plot = fpl.GridPlot(shape=(2, 2), controllers="sync")
+plot = fpl.GridPlot(shape=(2, 2), controller_ids="sync")
# to force a specific framework such as glfw:
# plot = fpl.GridPlot(canvas="glfw")
diff --git a/examples/desktop/scatter/scatter_size.py b/examples/desktop/scatter/scatter_size.py
index 5b6987b7c..2ad995584 100644
--- a/examples/desktop/scatter/scatter_size.py
+++ b/examples/desktop/scatter/scatter_size.py
@@ -9,16 +9,7 @@
import fastplotlib as fpl
# grid with 2 rows and 3 columns
-grid_shape = (2,1)
-
-# pan-zoom controllers for each view
-# views are synced if they have the
-# same controller ID
-controllers = [
- [0],
- [0]
-]
-
+grid_shape = (2, 1)
# you can give string names for each subplot within the gridplot
names = [
@@ -29,7 +20,6 @@
# Create the grid plot
plot = fpl.GridPlot(
shape=grid_shape,
- controllers=controllers,
names=names,
size=(1000, 1000)
)
@@ -53,4 +43,4 @@
if __name__ == "__main__":
print(__doc__)
- fpl.run()
\ No newline at end of file
+ fpl.run()
diff --git a/examples/desktop/screenshots/gridplot.png b/examples/desktop/screenshots/gridplot.png
index f2cbb1e7a..bc35ccf8c 100644
--- a/examples/desktop/screenshots/gridplot.png
+++ b/examples/desktop/screenshots/gridplot.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2705c69adab84f7740322b4a66ce33df00001dc7d51624becb8e88204113b028
-size 350236
+oid sha256:e416fc968edd3788513e369f4d265b0abd7216a7ef19ec8b84659c30ca7c8ca1
+size 307384
diff --git a/examples/desktop/screenshots/gridplot_non_square.png b/examples/desktop/screenshots/gridplot_non_square.png
index 7b534aef9..82b2b0eb4 100644
--- a/examples/desktop/screenshots/gridplot_non_square.png
+++ b/examples/desktop/screenshots/gridplot_non_square.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:abf936904d1b5e2018a72311c510108925f2972dfdf59166580ad27876f9e2be
-size 220140
+oid sha256:ab5598b67b80efce0d2559e400e77098e734c91608a3f49b691ddaa030d47edb
+size 203434
diff --git a/examples/desktop/screenshots/heatmap.png b/examples/desktop/screenshots/heatmap.png
index d0df1510a..a0655cf3a 100644
--- a/examples/desktop/screenshots/heatmap.png
+++ b/examples/desktop/screenshots/heatmap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6c19d6454e79d92074bac01175dfbb8506e882ea55b626c0b2357960ed6e294f
-size 163655
+oid sha256:6872c3cc3e35ec918b054fb2d76525bbd3d82d8b49916aca1046aa1be65ff923
+size 111825
diff --git a/examples/desktop/screenshots/heatmap_cmap.png b/examples/desktop/screenshots/heatmap_cmap.png
index db3038dee..2eb769c14 100644
--- a/examples/desktop/screenshots/heatmap_cmap.png
+++ b/examples/desktop/screenshots/heatmap_cmap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0328eec32f13042e3e2f243793317e180bba1353fe961604ecad3f38463b8809
-size 156419
+oid sha256:f2eba96c2bfb1d07365810a69e99c79b068741f5dcf74fc745c13d5ff21f16f2
+size 106671
diff --git a/examples/desktop/screenshots/heatmap_data.png b/examples/desktop/screenshots/heatmap_data.png
index 96169ec77..50a8ae79e 100644
--- a/examples/desktop/screenshots/heatmap_data.png
+++ b/examples/desktop/screenshots/heatmap_data.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4a376c24fa123088be69f807ec5212cb5ed5680b146ce9d62df584790c632845
-size 20838
+oid sha256:f0576063658e05e19b7723b4c88dc4d55a8178b090b4a88e33251fc92408b4a1
+size 18051
diff --git a/examples/desktop/screenshots/heatmap_vmin_vmax.png b/examples/desktop/screenshots/heatmap_vmin_vmax.png
index 2a809d545..f10382e87 100644
--- a/examples/desktop/screenshots/heatmap_vmin_vmax.png
+++ b/examples/desktop/screenshots/heatmap_vmin_vmax.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3eb12ad590aa8260f2cf722abadf5b51bcb7d5a8d8d1cb05b7711b50331da07a
-size 165937
+oid sha256:639d50f2f5fb07dba461e7a38de3886092f8754277eadbb5e305e32023289abd
+size 124403
diff --git a/examples/desktop/screenshots/image_cmap.png b/examples/desktop/screenshots/image_cmap.png
index cf3ae8ac0..bed07a41a 100644
--- a/examples/desktop/screenshots/image_cmap.png
+++ b/examples/desktop/screenshots/image_cmap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d9dcf05ca2953103b9960d9159ccb89dc257bf5e5c6d3906eeaaac9f71686439
-size 274882
+oid sha256:e1d78cc0681079a5c43d9fdb4142f5fee75d477d9f9a1469fca8bc8933c244fc
+size 216210
diff --git a/examples/desktop/screenshots/image_rgb.png b/examples/desktop/screenshots/image_rgb.png
index 5681017c8..a21c0658b 100644
--- a/examples/desktop/screenshots/image_rgb.png
+++ b/examples/desktop/screenshots/image_rgb.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:408e31db97278c584f4aaa0039099366fc8feb5693d15ab335205927d067c42a
-size 319585
+oid sha256:820a73b9b2e5bbaed84fb11438e2c5672b76c8b57a33823f4840a71be03d7dd1
+size 251438
diff --git a/examples/desktop/screenshots/image_rgbvminvmax.png b/examples/desktop/screenshots/image_rgbvminvmax.png
index aea5fdf85..88acfadc5 100644
--- a/examples/desktop/screenshots/image_rgbvminvmax.png
+++ b/examples/desktop/screenshots/image_rgbvminvmax.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d5dbe9a837b3503ca45eb83edbec7b1d7b6463093699af6b01b5303978af4b85
-size 44781
+oid sha256:5f2f562573f8104342ae01b5852f71c960341bdd70ae0bc7967df663166edbd3
+size 39604
diff --git a/examples/desktop/screenshots/image_simple.png b/examples/desktop/screenshots/image_simple.png
index 5ab073433..098d5a055 100644
--- a/examples/desktop/screenshots/image_simple.png
+++ b/examples/desktop/screenshots/image_simple.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4aa397a120ed1b232c4d56ffd3547ea42c2874aa54bfbdbffebfd34129059ccd
-size 272355
+oid sha256:a4ed42d042d8bb7e35f31b5ad0a3e3a495cf9c3164516eb457d8b41d7fae6bab
+size 213075
diff --git a/examples/desktop/screenshots/image_vminvmax.png b/examples/desktop/screenshots/image_vminvmax.png
index aea5fdf85..88acfadc5 100644
--- a/examples/desktop/screenshots/image_vminvmax.png
+++ b/examples/desktop/screenshots/image_vminvmax.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d5dbe9a837b3503ca45eb83edbec7b1d7b6463093699af6b01b5303978af4b85
-size 44781
+oid sha256:5f2f562573f8104342ae01b5852f71c960341bdd70ae0bc7967df663166edbd3
+size 39604
diff --git a/examples/desktop/screenshots/line.png b/examples/desktop/screenshots/line.png
index a38008ab9..cbc0a7b21 100644
--- a/examples/desktop/screenshots/line.png
+++ b/examples/desktop/screenshots/line.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1fe996cd43013ff2e616e8a549933137529c13ad8e320331420e9c64f6ed1690
-size 49738
+oid sha256:018f4a36c60b3de2f1406aa2823b751de5fae2c2340f9d49368d007ba7379637
+size 44422
diff --git a/examples/desktop/screenshots/line_cmap.png b/examples/desktop/screenshots/line_cmap.png
index 0ece6fbde..a07b15d36 100644
--- a/examples/desktop/screenshots/line_cmap.png
+++ b/examples/desktop/screenshots/line_cmap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c6f511ffd3a10e2c653afd3b9eca8f6bb10af26759a7efc73fe16c825cc1bf15
-size 43718
+oid sha256:c6df49f5f900caa217a5a0b01f601d6e83e1ee5c3a60c8968b9be837df785905
+size 43673
diff --git a/examples/desktop/screenshots/line_collection.png b/examples/desktop/screenshots/line_collection.png
index f7be75201..60ec82bc8 100644
--- a/examples/desktop/screenshots/line_collection.png
+++ b/examples/desktop/screenshots/line_collection.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4aa71b9b8d2c049dad951493a5f51c32da33a3e536761254cd18368d6b8cd8e8
-size 146755
+oid sha256:e0ddd75bc2fd8e4844ccb46c53fe463dc604927737ed00c8fb6b1c29fd2b1ab2
+size 146797
diff --git a/examples/desktop/screenshots/line_collection_cmap_values.png b/examples/desktop/screenshots/line_collection_cmap_values.png
index a91e4ce69..7223db9ee 100644
--- a/examples/desktop/screenshots/line_collection_cmap_values.png
+++ b/examples/desktop/screenshots/line_collection_cmap_values.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a32210432cd8e88bec20a84b1e6839d0a2d5bb2edb1aea8ebe09569872cb16d8
-size 93580
+oid sha256:311c7ef6f6f46e32983a5a531adc179b0179f382300f3cafbb6d8a7d4aeab565
+size 93676
diff --git a/examples/desktop/screenshots/line_collection_cmap_values_qualitative.png b/examples/desktop/screenshots/line_collection_cmap_values_qualitative.png
index c38e5fb96..500de82bb 100644
--- a/examples/desktop/screenshots/line_collection_cmap_values_qualitative.png
+++ b/examples/desktop/screenshots/line_collection_cmap_values_qualitative.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5be6f9343b47848d3e1be4b82315f0b71bdb1b919503f943c618ef8ba7f6272a
-size 95656
+oid sha256:8714dd43aa3d5c791fb9359e745895447d3a3234e3e8598d171ea3666a3fd7a3
+size 95660
diff --git a/examples/desktop/screenshots/line_collection_colors.png b/examples/desktop/screenshots/line_collection_colors.png
index 1ae597033..f60faae32 100644
--- a/examples/desktop/screenshots/line_collection_colors.png
+++ b/examples/desktop/screenshots/line_collection_colors.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b1e5b913ca91293a8edb8f6898249dd62019cb827223dacf377e3fc6cda89a77
-size 82686
+oid sha256:e2fad15985608a4c6b1fda3005dc89950b4cad5fed956f5d26672257385985d0
+size 82753
diff --git a/examples/desktop/screenshots/line_colorslice.png b/examples/desktop/screenshots/line_colorslice.png
index 003f86e44..7b652f165 100644
--- a/examples/desktop/screenshots/line_colorslice.png
+++ b/examples/desktop/screenshots/line_colorslice.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0033fc23cda3f07cdd7db642d4d1af710319d56a1690339354a9df27bf51c381
-size 57146
+oid sha256:5bd80cee80f491da6ab64c868a3c70254a68072e0bc0caad80c7999cadcb2df9
+size 50497
diff --git a/examples/desktop/screenshots/line_dataslice.png b/examples/desktop/screenshots/line_dataslice.png
index 20c777212..d68a554bd 100644
--- a/examples/desktop/screenshots/line_dataslice.png
+++ b/examples/desktop/screenshots/line_dataslice.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2a169b359a0e56bb48a625069e73e53b26e061e6bcb83d6eb613fbdd1a43cdac
-size 75385
+oid sha256:823651905a775b5cbcc2ce0f79d25d69b29f17b4c060c244d80ae87019f05d5b
+size 69332
diff --git a/examples/desktop/screenshots/line_present_scaling.png b/examples/desktop/screenshots/line_present_scaling.png
index c4a41ac2e..02cd2b1f8 100644
--- a/examples/desktop/screenshots/line_present_scaling.png
+++ b/examples/desktop/screenshots/line_present_scaling.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c67d65b0a5120c014b34dcfc326079113cee22b849c14a0284fc7881dac5d43c
-size 43446
+oid sha256:3d18669d5e75cee3326d0380ae5dd26cab71ea97725ff99bc5228d2555d51454
+size 30373
diff --git a/examples/desktop/screenshots/line_stack.png b/examples/desktop/screenshots/line_stack.png
index 23343df32..443184247 100644
--- a/examples/desktop/screenshots/line_stack.png
+++ b/examples/desktop/screenshots/line_stack.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:bc2496c203b2994ef5b8e714e1c7619e726d0b605e0c25498f11e1154d4905ec
-size 360981
+oid sha256:29580e5ebb0597d54adb2b7f2f91de44e4480cf23c0c271ee44426203b4c1c44
+size 360892
diff --git a/examples/desktop/screenshots/scatter.png b/examples/desktop/screenshots/scatter.png
index e35fd9e3c..bf5e8c92a 100644
--- a/examples/desktop/screenshots/scatter.png
+++ b/examples/desktop/screenshots/scatter.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e2efb81fb8b6b11bb1fc3136394c0f6bf1c38972d03dabd07949928f4e53cf71
-size 25240
+oid sha256:bd38399b77e09d915c5bb1e7ee022f936ae90682f598357bc774a95c372dc78f
+size 25231
diff --git a/examples/desktop/screenshots/scatter_cmap.png b/examples/desktop/screenshots/scatter_cmap.png
index 10477e81b..eec22566a 100644
--- a/examples/desktop/screenshots/scatter_cmap.png
+++ b/examples/desktop/screenshots/scatter_cmap.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8b4b364d1cd3ab328f025030db87f8ff4fb2544c3bfb67176ea8f0acdc24f04b
-size 59407
+oid sha256:e712693b403166909dcaa65256131eacba0a15892cd144ad97fdecb6b9835e93
+size 57273
diff --git a/examples/desktop/screenshots/scatter_colorslice.png b/examples/desktop/screenshots/scatter_colorslice.png
index cd5a1f00d..0da0fcd9f 100644
--- a/examples/desktop/screenshots/scatter_colorslice.png
+++ b/examples/desktop/screenshots/scatter_colorslice.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0d3afcf293e425c2369d93745cb933afb15d971866620f160629e394f50cd9b6
-size 23747
+oid sha256:c620cad9976f390e44a5b037f3ff61fb80e6487e17f4be8118be5df55f276a35
+size 23664
diff --git a/examples/desktop/screenshots/scatter_dataslice.png b/examples/desktop/screenshots/scatter_dataslice.png
index 8ed7ad590..32f56ad11 100644
--- a/examples/desktop/screenshots/scatter_dataslice.png
+++ b/examples/desktop/screenshots/scatter_dataslice.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:974111967bc5e4197b6b38c7a00950ee013ce4e689162c9d91e902d37240221a
-size 26001
+oid sha256:69d2f0999b0bb334e48320702095fc76444f4d89d43a51ac6c5c8f49e1df96ac
+size 25999
diff --git a/examples/desktop/screenshots/scatter_present.png b/examples/desktop/screenshots/scatter_present.png
index 335191d91..8c1e5eed4 100644
--- a/examples/desktop/screenshots/scatter_present.png
+++ b/examples/desktop/screenshots/scatter_present.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fb5b0bf6fb7b7dbfafc1b2553dfff87f329ec5070fb69061313acce46364df52
-size 24627
+oid sha256:e45c1a936771e569e562ed3496421e498e725325093e84243ab494c0718ead3a
+size 23639
diff --git a/examples/desktop/screenshots/scatter_size.png b/examples/desktop/screenshots/scatter_size.png
index 1d0f91f9c..da211cde1 100644
--- a/examples/desktop/screenshots/scatter_size.png
+++ b/examples/desktop/screenshots/scatter_size.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3eb05d8a18aada52a6ab02a0d3d030aab97510aace226cf3967e5c5c1cd3274d
-size 66044
+oid sha256:10533aa5831a50a0f9b38c0a60b89a9b6c33311ecb3a569c5e0b4c82379dc20a
+size 66037
diff --git a/examples/notebooks/gridplot.ipynb b/examples/notebooks/gridplot.ipynb
index cfcae3705..f1ceb2180 100644
--- a/examples/notebooks/gridplot.ipynb
+++ b/examples/notebooks/gridplot.ipynb
@@ -10,7 +10,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"id": "a635b3b3-33fa-48f0-b1cc-bf83b1e883ab",
"metadata": {},
"outputs": [],
@@ -21,52 +21,10 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"id": "8de931e2-bdb3-44a3-9538-e0b3965779af",
"metadata": {},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "62f67ebf3b00494c826d92fc5b8bbf76",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "RFBOutputContext()"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "

initial snapshot
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "b6262056cff84619aea08fc48d00eb79",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "JupyterWgpuCanvas()"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# grid with 2 rows and 3 columns\n",
"grid_shape = (2, 3)\n",
@@ -74,9 +32,15 @@
"# pan-zoom controllers for each view\n",
"# views are synced if they have the \n",
"# same controller ID\n",
- "controllers = [\n",
- " [0, 3, 1], # id each controller with an integer\n",
- " [2, 2, 3]\n",
+ "controller_ids = [\n",
+ " [0, -3, 1], # id each controller with an integer\n",
+ " [2, 2, -3]\n",
+ "]\n",
+ "\n",
+ "# another way to set controller_ids\n",
+ "controller_ids = [\n",
+ " [\"subplot0\", \"subplot4\"],\n",
+ " [\"subplot1\", \"subplot2\", \"subplot5\"],\n",
"]\n",
"\n",
"\n",
@@ -89,7 +53,7 @@
"# Create the grid plot\n",
"grid_plot = GridPlot(\n",
" shape=grid_shape,\n",
- " controllers=controllers,\n",
+ " controller_ids=controller_ids,\n",
" names=names,\n",
")\n",
"\n",
@@ -123,24 +87,10 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"id": "2a6f7eb5-776e-42a6-b6c2-c26009a26795",
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "subplot0: Subplot @ 0x7fd496b32830\n",
- " parent: None\n",
- " Graphics:\n",
- "\t'rand-image': ImageGraphic @ 0x7fd496b327d0"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# can access subplot by name\n",
"grid_plot[\"subplot0\"]"
@@ -148,24 +98,10 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": null,
"id": "45e83bca-5a44-48ce-874f-9ae9ca444233",
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "subplot0: Subplot @ 0x7fd496b32830\n",
- " parent: None\n",
- " Graphics:\n",
- "\t'rand-image': ImageGraphic @ 0x7fd496b327d0"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# can access subplot by index\n",
"grid_plot[0, 0]"
@@ -182,21 +118,10 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": null,
"id": "c8cf9bfd-e0cc-4173-b64e-a9f2c87bb2c6",
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'rand-image': ImageGraphic @ 0x7fd496b327d0"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# can access graphic directly via name\n",
"grid_plot[\"subplot0\"][\"rand-image\"]"
@@ -204,13 +129,13 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"id": "1cfd1d45-8a60-4fc1-b873-46caa966fe6f",
"metadata": {},
"outputs": [],
"source": [
- "grid_plot[\"subplot0\"][\"rand-image\"].vmin = 0.6\n",
- "grid_plot[\"subplot0\"][\"rand-image\"].vmax = 0.8"
+ "grid_plot[\"subplot0\"][\"rand-image\"].cmap.vmin = 0.6\n",
+ "grid_plot[\"subplot0\"][\"rand-image\"].cmap.vmax = 0.8"
]
},
{
@@ -223,40 +148,19 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": null,
"id": "2fafe992-4783-40f2-b044-26a2835dd50a",
"metadata": {},
"outputs": [],
"source": [
- "grid_plot[1, 0][\"rand-image\"].vim = 0.1\n",
- "grid_plot[1, 0][\"rand-image\"].vmax = 0.3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "id": "a025b76c-77f8-4aeb-ac33-5bb6d0bb5a9a",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'image'"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "grid_plot[1, 0][\"rand-image\"].type"
+ "grid_plot[1, 0][\"rand-image\"].cmap.vim = 0.1\n",
+ "grid_plot[1, 0][\"rand-image\"].cmap.vmax = 0.3"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "62584f91-a8ed-4317-98ee-28ad6d1800d6",
+ "id": "a61e34a5-ee1b-4abb-8718-ec4715ffaa52",
"metadata": {},
"outputs": [],
"source": []
@@ -278,7 +182,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.10.5"
+ "version": "3.11.3"
}
},
"nbformat": 4,
diff --git a/examples/notebooks/gridplot_simple.ipynb b/examples/notebooks/gridplot_simple.ipynb
index 8b50b2701..74807f55a 100644
--- a/examples/notebooks/gridplot_simple.ipynb
+++ b/examples/notebooks/gridplot_simple.ipynb
@@ -10,9 +10,13 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"id": "5171a06e-1bdc-4908-9726-3c1fd45dbb9d",
"metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-11-26T04:01:19.120171Z",
+ "start_time": "2023-11-26T04:01:18.618087Z"
+ },
"tags": []
},
"outputs": [],
@@ -23,38 +27,19 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"id": "86a2488f-ae1c-4b98-a7c0-18eae8013af1",
"metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-11-26T04:01:19.467264Z",
+ "start_time": "2023-11-26T04:01:19.121813Z"
+ },
"tags": []
},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "f9067cd724094b8c8dfecf60208acbfa",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "RFBOutputContext()"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/clewis7/repos/fastplotlib/fastplotlib/graphics/_features/_base.py:34: UserWarning: converting float64 array to float32\n",
- " warn(f\"converting {array.dtype} array to float32\")\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# GridPlot of shape 2 x 3 with all controllers synced\n",
- "grid_plot = GridPlot(shape=(2, 3), controllers=\"sync\")\n",
+ "grid_plot = GridPlot(shape=(2, 3), controller_ids=\"sync\")\n",
"\n",
"# Make a random image graphic for each subplot\n",
"for subplot in grid_plot:\n",
@@ -88,27 +73,22 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
+ "id": "52163bc7-2c77-4699-b7b0-e455a0ed7584",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "grid_plot"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"id": "17c6bc4a-5340-49f1-8597-f54528cfe915",
"metadata": {
"tags": []
},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "unnamed: Subplot @ 0x7f15df4f5c50\n",
- " parent: fastplotlib.GridPlot @ 0x7f15d3f27890\n",
- "\n",
- " Graphics:\n",
- "\t'rand-img': ImageGraphic @ 0x7f15d3fb5390"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# positional indexing\n",
"# row 0 and col 0\n",
@@ -125,23 +105,12 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": null,
"id": "34130f12-9ef6-43b0-b929-931de8b7da25",
"metadata": {
"tags": []
},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(,)"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"grid_plot[0, 1].graphics"
]
@@ -156,7 +125,7 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": null,
"id": "ef8a29a6-b19c-4e6b-a2ba-fb4823c01451",
"metadata": {
"tags": []
@@ -176,7 +145,7 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"id": "d6c2fa4b-c634-4dcf-8b61-f1986f7c4918",
"metadata": {
"tags": []
@@ -189,50 +158,24 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": null,
"id": "2f6b549c-3165-496d-98aa-45b96c3de674",
"metadata": {
"tags": []
},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "top-right-plot: Subplot @ 0x7f15d3f769d0\n",
- " parent: fastplotlib.GridPlot @ 0x7f15d3f27890\n",
- "\n",
- " Graphics:\n",
- "\t'rand-img': ImageGraphic @ 0x7f15b83f7250"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"grid_plot[\"top-right-plot\"]"
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": null,
"id": "be436e04-33a6-4597-8e6a-17e1e5225419",
"metadata": {
"tags": []
},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(0, 2)"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# view its position\n",
"grid_plot[\"top-right-plot\"].position"
@@ -240,23 +183,12 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": null,
"id": "6699cda6-af86-4258-87f5-1832f989a564",
"metadata": {
"tags": []
},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# these are really the same\n",
"grid_plot[\"top-right-plot\"] is grid_plot[0, 2]"
@@ -272,19 +204,19 @@
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": null,
"id": "545b627b-d794-459a-a75a-3fde44f0ea95",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
- "grid_plot[\"top-right-plot\"][\"rand-img\"].vmin = 0.5"
+ "grid_plot[\"top-right-plot\"][\"rand-img\"].cmap.vmin = 0.5"
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": null,
"id": "36432d5b-b76c-4a2a-a32c-097faf5ab269",
"metadata": {
"tags": []
diff --git a/examples/notebooks/image_widget.ipynb b/examples/notebooks/image_widget.ipynb
index d8f91c1be..56d5c8a81 100644
--- a/examples/notebooks/image_widget.ipynb
+++ b/examples/notebooks/image_widget.ipynb
@@ -10,7 +10,9 @@
"outputs": [],
"source": [
"from fastplotlib.widgets import ImageWidget\n",
- "import numpy as np"
+ "import numpy as np\n",
+ "\n",
+ "import imageio.v3 as iio # not a fastplotlib dependency, only used for examples"
]
},
{
@@ -30,7 +32,8 @@
},
"outputs": [],
"source": [
- "a = np.random.rand(512, 512)"
+ "# image widget only supports grayscale images for now\n",
+ "a = iio.imread(\"imageio:camera.png\")"
]
},
{
@@ -63,7 +66,7 @@
"id": "b718162f-9aa6-4091-a7a4-c620676b48bd",
"metadata": {},
"source": [
- "### can dynamically change features"
+ "### Access graphics managed by the image widget"
]
},
{
@@ -75,7 +78,7 @@
},
"outputs": [],
"source": [
- "iw.gridplot[0, 0].graphics[0].cmap = \"gnuplot2\""
+ "iw.gridplot[0, 0][\"image_widget_managed\"].cmap = \"gnuplot2\""
]
},
{
@@ -95,7 +98,10 @@
},
"outputs": [],
"source": [
- "a = np.random.rand(500, 512, 512)"
+ "movie = iio.imread(\"imageio:cockatoo.mp4\")\n",
+ "\n",
+ "# convert RGB movie to grayscale, this could take a minute\n",
+ "gray_movie = np.dot(movie[..., :3], [0.299, 0.587, 0.114])"
]
},
{
@@ -107,10 +113,10 @@
},
"outputs": [],
"source": [
- "iw2 = ImageWidget(\n",
- " data=a, \n",
+ "iw_movie = ImageWidget(\n",
+ " data=gray_movie, \n",
" slider_dims=[\"t\"],\n",
- " cmap=\"gnuplot2\"\n",
+ " cmap=\"gray\"\n",
")"
]
},
@@ -123,7 +129,7 @@
},
"outputs": [],
"source": [
- "iw2.show()"
+ "iw_movie.show(sidecar=True)"
]
},
{
@@ -146,7 +152,7 @@
"outputs": [],
"source": [
"# must be in the form of {dim: (func, window_size)}\n",
- "iw2.window_funcs = {\"t\": (np.mean, 13)}"
+ "iw_movie.window_funcs = {\"t\": (np.mean, 13)}"
]
},
{
@@ -159,7 +165,7 @@
"outputs": [],
"source": [
"# change the winow size\n",
- "iw2.window_funcs[\"t\"].window_size = 23"
+ "iw_movie.window_funcs[\"t\"].window_size = 33"
]
},
{
@@ -172,7 +178,7 @@
"outputs": [],
"source": [
"# change the function\n",
- "iw2.window_funcs[\"t\"].func = np.max"
+ "iw_movie.window_funcs[\"t\"].func = np.max"
]
},
{
@@ -184,8 +190,8 @@
},
"outputs": [],
"source": [
- "# or set it again\n",
- "iw2.window_funcs = {\"t\": (np.min, 11)}"
+ "# or reset it\n",
+ "iw_movie.window_funcs = None"
]
},
{
@@ -196,6 +202,26 @@
"### Can also set new data"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f9ee0e42-3d41-4613-a508-042c6c2c27e3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "new_data = iio.imread(\"imageio:stent.npz\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b85d2e08-1479-46fc-a429-2d7a265493d4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "new_data.shape"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -205,8 +231,18 @@
},
"outputs": [],
"source": [
- "new_data = np.random.rand(500, 512, 512)\n",
- "iw2.set_data(new_data=new_data)"
+ "iw_movie.set_data(new_data=new_data)\n",
+ "iw_movie.gridplot[0, 0].auto_scale()# sidecar is optional"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3d323f67-4717-4241-ad84-5091e6caf2cd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw_movie.close()"
]
},
{
@@ -214,7 +250,7 @@
"id": "aca22179-1b1f-4c51-97bf-ce2d7044e451",
"metadata": {},
"source": [
- "# Gridplot of txy data"
+ "# Gridplot of tzxy data"
]
},
{
@@ -226,8 +262,29 @@
},
"outputs": [],
"source": [
- "dims = (100, 512, 512)\n",
- "data = [np.random.rand(*dims) for i in range(4)]"
+ "zfish_data = np.load(\"./zfish_test.npy\")\n",
+ "# snippet of a dataset from Martin Haesemeyer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b015720c-3de1-4575-80c5-d6eabe4b305f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# data is tzxy\n",
+ "zfish_data.shape"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fdff388e-d44c-41ff-a177-801f2695fb88",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n_planes = zfish_data.shape[1]"
]
},
{
@@ -239,22 +296,20 @@
},
"outputs": [],
"source": [
- "iw3 = ImageWidget(\n",
- " data=data, \n",
- " slider_dims=[\"t\"], \n",
- " # dims_order=\"txy\", # you can set this manually if dim order is not the usual\n",
- " names=[\"zero\", \"one\", \"two\", \"three\"],\n",
+ "iw_zfish = ImageWidget(\n",
+ " data=[zfish_data[:, i] for i in range(n_planes)],\n",
" window_funcs={\"t\": (np.mean, 5)},\n",
+ " names=[f\"plane-{i}\" for i in range(n_planes)],\n",
" cmap=\"gnuplot2\", \n",
")"
]
},
{
"cell_type": "markdown",
- "id": "0721dc40-677e-431d-94c6-da59606199cb",
+ "id": "037d899e-9e7c-4d58-a021-5f5b71e1db90",
"metadata": {},
"source": [
- "### pan-zoom controllers are all synced in a `ImageWidget`"
+ "pan-zoom controllers are all synced across subplots in a `ImageWidget`"
]
},
{
@@ -266,7 +321,7 @@
},
"outputs": [],
"source": [
- "iw3.show()"
+ "iw_zfish.show(sidecar=True)"
]
},
{
@@ -274,7 +329,7 @@
"id": "82545214-13c4-475e-87da-962117085834",
"metadata": {},
"source": [
- "### Index the subplots using the names given to `ImageWidget`"
+ "Access the subplots using the names given to `ImageWidget`"
]
},
{
@@ -286,7 +341,7 @@
},
"outputs": [],
"source": [
- "iw3.gridplot[\"two\"]"
+ "iw_zfish.gridplot[\"plane-2\"]"
]
},
{
@@ -294,7 +349,7 @@
"id": "dc727d1a-681e-4cbf-bfb2-898ceb31cbe0",
"metadata": {},
"source": [
- "### change window functions just like before"
+ "change window functions"
]
},
{
@@ -306,70 +361,110 @@
},
"outputs": [],
"source": [
- "iw3.window_funcs[\"t\"].func = np.max"
+ "iw_zfish.window_funcs[\"t\"].func = np.max"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ceeab465-bafa-4834-8775-d0e35bc5c880",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw_zfish.window_funcs = None"
]
},
{
"cell_type": "markdown",
- "id": "3e89c10f-6e34-4d63-9805-88403d487432",
+ "id": "8e16a503-0213-4e83-abd3-d1fd202cc193",
"metadata": {},
"source": [
- "## Gridplot of volumetric data"
+ "**Frame-apply functions**\n",
+ "\n",
+ "These are applied on a frame before being displayed in the `ImageGraphic`"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "b1587410-a08e-484c-8795-195a413d6374",
- "metadata": {
- "tags": []
- },
+ "id": "9557f0a1-b8fd-4dfe-ac3f-47c90ce78625",
+ "metadata": {},
"outputs": [],
"source": [
- "dims = (256, 256, 5, 100)\n",
- "data = [np.random.rand(*dims) for i in range(4)]\n",
- "\n",
- "iw4 = ImageWidget(\n",
- " data=data, \n",
- " slider_dims=[\"t\", \"z\"], \n",
- " dims_order=\"xyzt\", # example of how you can set this for non-standard orders\n",
- " names=[\"zero\", \"one\", \"two\", \"three\"],\n",
- " # window_funcs={\"t\": (np.mean, 5)}, # window functions can be slow when indexing multiple dims\n",
- " cmap=\"gnuplot2\", \n",
- ")"
+ "# scipy isn't a fastplotlib dependency, it's just used for this example\n",
+ "from scipy.ndimage import gaussian_filter"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "3ccea6c6-9580-4720-bce8-a5507cf867a3",
- "metadata": {
- "tags": []
- },
+ "id": "f87d7e33-93bc-46e3-9cd1-6c648b132841",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw_zfish.frame_apply = lambda frame: gaussian_filter(frame.astype(np.float32), sigma=3)\n",
+ "iw_zfish.reset_vmin_vmax()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8b0aa161-89f1-48e4-9976-4a6996f1e7e9",
+ "metadata": {},
"outputs": [],
"source": [
- "iw4.show()"
+ "# remove the frame-apply function\n",
+ "iw_zfish.frame_apply = None\n",
+ "iw_zfish.reset_vmin_vmax()"
]
},
{
"cell_type": "markdown",
- "id": "2382809c-4c7d-4da4-9955-71d316dee46a",
+ "id": "3e89c10f-6e34-4d63-9805-88403d487432",
"metadata": {},
"source": [
- "### window functions, can be slow when you have \"t\" and \"z\""
+ "## z-sliders\n",
+ "\n",
+ "ImageWidget will also give you a slider for \"z\" in addition to \"t\" if necessary. \n",
+ "\n",
+ "This example uses the same example data shown above, but displays them in a single subplot and `ImageWidget` provides a z-slider. You can use `window_funcs`, `frame_apply` funcs, etc. There is no difference in `ImageWidget` behavior with the z-slider."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b1587410-a08e-484c-8795-195a413d6374",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_z = ImageWidget(\n",
+ " data=zfish_data, # you can also provide a list of tzxy arrays\n",
+ " window_funcs={\"t\": (np.mean, 5)},\n",
+ " cmap=\"gnuplot2\", \n",
+ ")"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "fd4433a9-2add-417c-a618-5891371efae0",
+ "id": "3ccea6c6-9580-4720-bce8-a5507cf867a3",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
- "iw4.window_funcs = {\"t\": (np.mean, 11)}"
+ "iw_z.show()"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aba0fa3a-f844-4937-8615-adbded02345d",
+ "metadata": {},
+ "outputs": [],
+ "source": []
}
],
"metadata": {
diff --git a/examples/notebooks/image_widget_test.ipynb b/examples/notebooks/image_widget_test.ipynb
new file mode 100644
index 000000000..90747757c
--- /dev/null
+++ b/examples/notebooks/image_widget_test.ipynb
@@ -0,0 +1,470 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "07019035-83f2-4753-9e7c-628ae439b441",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "from fastplotlib.widgets import ImageWidget\n",
+ "import numpy as np\n",
+ "from scipy.ndimage import gaussian_filter\n",
+ "\n",
+ "import imageio.v3 as iio"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10b8ab40-944d-472c-9b7e-cae8a129e7ce",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from nb_test_utils import plot_test, notebook_finished "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0a9fe48a-cc24-4ecf-b442-b7425ce338d3",
+ "metadata": {},
+ "source": [
+ "# Single image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "01dd4b84-2960-4c26-8162-f0499698e593",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "a = iio.imread(\"imageio:camera.png\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f9d98a12-9574-4b47-9271-013e659cb93f",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw = ImageWidget(\n",
+ " data=a,\n",
+ " cmap=\"viridis\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e9d86a12-b5f2-4ad7-bd70-4715c80b5ece",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "920ef882-e5e6-45b6-b002-5ed26aa3134e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_test(\"image-widget-single\", iw.gridplot)\n",
+ "iw.gridplot[0, 0][\"image_widget_managed\"].cmap = \"gnuplot2\"\n",
+ "plot_test(\"image-widget-single-gnuplot2\", iw.gridplot)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "26120b76-c7b0-4e23-bdb1-411be1944687",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ffde9820-b388-4f22-b7fd-d55a2ad421ad",
+ "metadata": {},
+ "source": [
+ "# Single image sequence"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2067c88f-2b71-4036-a413-59355fa64292",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "movie = iio.imread(\"imageio:cockatoo.mp4\")\n",
+ "\n",
+ "# convert RGB movie to grayscale, this could take a minute\n",
+ "gray_movie = np.dot(movie[..., :3], [0.299, 0.587, 0.114])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "05d3a905-849b-42ae-82ac-34bdc28c1414",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_movie = ImageWidget(\n",
+ " data=gray_movie, \n",
+ " slider_dims=[\"t\"],\n",
+ " cmap=\"gray\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "92df8b8c-8d9f-4111-9b3b-fdab7cc7b3f4",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_movie.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ac0a7fc0-0323-4b9e-8c70-3ddc735b7893",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# testing cell ignore\n",
+ "assert iw_movie.sliders[\"t\"].max == gray_movie.shape[0] - 1\n",
+ "assert iw_movie.sliders[\"t\"].min == 0\n",
+ "plot_test(\"image-widget-movie-single-0\", iw_movie.gridplot)\n",
+ "iw_movie.sliders[\"t\"].value = 50\n",
+ "plot_test(\"image-widget-movie-single-50\", iw_movie.gridplot)\n",
+ "iw_movie.sliders[\"t\"].value = 279\n",
+ "plot_test(\"image-widget-movie-single-279\", iw_movie.gridplot)\n",
+ "iw_movie.sliders[\"t\"].value = 0\n",
+ "plot_test(\"image-widget-movie-single-0-reset\", iw_movie.gridplot)\n",
+ "iw_movie.sliders[\"t\"].value = 50\n",
+ "iw_movie.window_funcs = {\"t\": (np.mean, 13)}\n",
+ "# testing cell ignore\n",
+ "plot_test(\"image-widget-movie-single-50-window-mean-13\", iw_movie.gridplot)\n",
+ "iw_movie.window_funcs[\"t\"].window_size = 33\n",
+ "plot_test(\"image-widget-movie-single-50-window-mean-33\", iw_movie.gridplot)\n",
+ "iw_movie.window_funcs[\"t\"].func = np.max\n",
+ "plot_test(\"image-widget-movie-single-50-window-max-33\", iw_movie.gridplot)\n",
+ "iw_movie.window_funcs = None\n",
+ "plot_test(\"image-widget-movie-single-50-window-reset\", iw_movie.gridplot)\n",
+ "iw_movie.sliders[\"t\"].value = 0"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c5fb9aaa-b1a8-46b9-81a5-a656183ab16d",
+ "metadata": {},
+ "source": [
+ "# Set new data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e1730287-41de-4166-8d00-36ae2daabb47",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "new_data = iio.imread(\"imageio:stent.npz\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9010dd43-83c8-4807-8874-71af8ef5c955",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_movie.set_data(new_data=new_data)\n",
+ "iw_movie.gridplot[0, 0].auto_scale()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "06e6f4fb-fe58-40f0-adf0-191e02cdbd75",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_test(\"image-widget-movie-set_data\", iw_movie.gridplot)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e5d55d4e-57f2-4460-b252-7a9d21f7c217",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw_movie.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d2e6819b-209a-49af-97b7-0b8956023d1a",
+ "metadata": {},
+ "source": [
+ "# zfish"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cf9845b6-1cda-403b-96cd-e2b51803c96a",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "zfish_data = np.load(\"./zfish_test.npy\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f7f0315a-29c0-4852-9d49-edaeb3ee45c6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# data is tzxy\n",
+ "zfish_data.shape"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "67e840fa-9eb9-4705-ab85-ec981ba29abb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n_planes = zfish_data.shape[1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "76535d56-e514-4c16-aa48-a6359f8019d5",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_zfish = ImageWidget(\n",
+ " data=[zfish_data[:, i] for i in range(n_planes)],\n",
+ " window_funcs={\"t\": (np.mean, 5)},\n",
+ " names=[f\"plane-{i}\" for i in range(n_planes)],\n",
+ " cmap=\"gnuplot2\", \n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13904849-cbc5-41e7-ad90-d6e8a4fc0077",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_zfish.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "75e8cf08-f1d2-414c-84a2-1ba4c2a01072",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# testing cell ignore\n",
+ "assert iw_zfish.sliders[\"t\"].max == zfish_data.shape[0] - 1\n",
+ "assert iw_zfish.sliders[\"t\"].min == 0\n",
+ "plot_test(\"image-widget-zfish-grid-init-mean-window-5\", iw_zfish.gridplot)\n",
+ "iw_zfish.sliders[\"t\"].value = 50\n",
+ "plot_test(\"image-widget-zfish-grid-frame-50-mean-window-5\", iw_zfish.gridplot)\n",
+ "iw_zfish.window_funcs[\"t\"].window_size = 13\n",
+ "plot_test(\"image-widget-zfish-grid-frame-50-mean-window-13\", iw_zfish.gridplot)\n",
+ "iw_zfish.window_funcs = None\n",
+ "plot_test(\"image-widget-zfish-grid-frame-50\", iw_zfish.gridplot)\n",
+ "iw_zfish.sliders[\"t\"].value = 99\n",
+ "plot_test(\"image-widget-zfish-grid-frame-99\", iw_zfish.gridplot)\n",
+ "iw_zfish.sliders[\"t\"].value = 50\n",
+ "iw_zfish.window_funcs = {\"t\": (np.max, 13)}\n",
+ "plot_test(\"image-widget-zfish-grid-frame-50-max-window-13\", iw_zfish.gridplot)\n",
+ "iw_zfish.window_funcs = None\n",
+ "iw_zfish.frame_apply = lambda frame: gaussian_filter(frame.astype(np.float32), sigma=3)\n",
+ "iw_zfish.reset_vmin_vmax()\n",
+ "plot_test(\"image-widget-zfish-grid-frame-50-frame-apply-gaussian\", iw_zfish.gridplot)\n",
+ "iw_zfish.frame_apply = None\n",
+ "iw_zfish.reset_vmin_vmax()\n",
+ "plot_test(\"image-widget-zfish-grid-frame-50-frame-apply-reset\", iw_zfish.gridplot)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "34499f45-cab3-4abd-832a-a679746b1684",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# reverse planes and test set_data\n",
+ "iw_zfish.set_data(\n",
+ " [zfish_data[:, i] for i in range(n_planes - 1, -1, -1)],\n",
+ " reset_indices=False\n",
+ ")\n",
+ "\n",
+ "plot_test(\"image-widget-zfish-grid-set_data-reset-indices-false\", iw_zfish.gridplot)\n",
+ "\n",
+ "iw_zfish.set_data(\n",
+ " [zfish_data[:, i] for i in range(n_planes - 1, -1, -1)],\n",
+ " reset_indices=True\n",
+ ")\n",
+ "plot_test(\"image-widget-zfish-grid-set_data-reset-indices-true\", iw_zfish.gridplot)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "08501aad-8b56-4ae5-98ff-26942cbb5d67",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw_zfish.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bf5ff2c3-780c-41dd-91a7-74ef8b87d838",
+ "metadata": {},
+ "source": [
+ "## z-sliders"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "87280ff7-5009-46a7-9306-0c1fe03ba4bd",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_z = ImageWidget(\n",
+ " data=zfish_data, # you can also provide a list of tzxy arrays\n",
+ " window_funcs={\"t\": (np.mean, 5)},\n",
+ " cmap=\"gnuplot2\", \n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "94142bdf-78d0-4512-b27a-f5a61b9aba5f",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "iw_z.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "06b66964-b3bf-4545-a0e6-79ddc996a1d0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# same tests as with the gridplot\n",
+ "assert iw_z.sliders[\"t\"].max == zfish_data.shape[0] - 1\n",
+ "assert iw_z.sliders[\"t\"].min == 0\n",
+ "plot_test(\"image-widget-zfish-init-mean-window-5\", iw_z.gridplot)\n",
+ "iw_z.sliders[\"t\"].value = 50\n",
+ "plot_test(\"image-widget-zfish-frame-50-mean-window-5\", iw_z.gridplot)\n",
+ "iw_z.window_funcs[\"t\"].window_size = 13\n",
+ "plot_test(\"image-widget-zfish-frame-50-mean-window-13\", iw_z.gridplot)\n",
+ "iw_z.window_funcs = None\n",
+ "plot_test(\"image-widget-zfish-frame-50\", iw_z.gridplot)\n",
+ "iw_z.sliders[\"t\"].value = 99\n",
+ "plot_test(\"image-widget-zfish-frame-99\", iw_z.gridplot)\n",
+ "iw_z.sliders[\"t\"].value = 50\n",
+ "iw_z.window_funcs = {\"t\": (np.max, 13)}\n",
+ "plot_test(\"image-widget-zfish-frame-50-max-window-13\", iw_z.gridplot)\n",
+ "iw_z.window_funcs = None\n",
+ "iw_z.frame_apply = lambda frame: gaussian_filter(frame.astype(np.float32), sigma=3)\n",
+ "iw_z.reset_vmin_vmax()\n",
+ "plot_test(\"image-widget-zfish-frame-50-frame-apply-gaussian\", iw_z.gridplot)\n",
+ "iw_z.frame_apply = None\n",
+ "iw_z.reset_vmin_vmax()\n",
+ "plot_test(\"image-widget-zfish-frame-50-frame-apply-reset\", iw_z.gridplot)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b94ae517-4a48-4efe-b85b-7679ae02d233",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "iw_z.close()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "870627ef-09d8-44e4-8952-aedb702d1526",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "notebook_finished()"
+ ]
+ }
+ ],
+ "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.11.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/examples/notebooks/lineplot.ipynb b/examples/notebooks/lineplot.ipynb
index e156a7150..667cae178 100644
--- a/examples/notebooks/lineplot.ipynb
+++ b/examples/notebooks/lineplot.ipynb
@@ -12,7 +12,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"id": "9c974494-712e-4981-bae2-a3ee176a6b20",
"metadata": {},
"outputs": [],
@@ -23,7 +23,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"id": "c3d8f967-f60f-4f0b-b6ba-21b1251b4856",
"metadata": {},
"outputs": [],
@@ -41,60 +41,10 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"id": "78cffe56-1147-4255-82c1-53cec6bc986a",
"metadata": {},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "7993e0a4358f4678a7343b78b3b0b24c",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "RFBOutputContext()"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/kushalk/repos/fastplotlib/fastplotlib/layouts/_base.py:214: UserWarning: `center_scene()` not yet implemented for `PerspectiveCamera`\n",
- " warn(\"`center_scene()` not yet implemented for `PerspectiveCamera`\")\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "
initial snapshot
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "898a109f489741a5b4624be77bd27db0",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "JupyterWgpuCanvas()"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# grid with 2 rows and 2 columns\n",
"shape = (2, 2)\n",
@@ -104,7 +54,7 @@
"# same controller ID\n",
"# in this example the first view has its own controller\n",
"# and the last 3 views are synced\n",
- "controllers = [\n",
+ "controller_ids = [\n",
" [0, 1], # id each controller with an integer\n",
" [1, 1]\n",
"]\n",
@@ -113,7 +63,7 @@
"grid_plot = GridPlot(\n",
" shape=shape,\n",
" cameras='3d', # 3D view for all subplots within the grid\n",
- " controllers=controllers\n",
+ " controller_ids=controller_ids\n",
")\n",
"\n",
"for i, subplot in enumerate(grid_plot):\n",
diff --git a/examples/notebooks/scatter.ipynb b/examples/notebooks/scatter.ipynb
index 948403f11..9d7ff099f 100644
--- a/examples/notebooks/scatter.ipynb
+++ b/examples/notebooks/scatter.ipynb
@@ -78,7 +78,7 @@
"# same controller ID\n",
"# you can only sync controllers that use the same camera type\n",
"# i.e. you cannot sync between 2d and 3d subplots\n",
- "controllers = [\n",
+ "controller_ids = [\n",
" [0, 1],\n",
" [1, 0]\n",
"]\n",
@@ -87,7 +87,7 @@
"grid_plot = GridPlot(\n",
" shape=shape,\n",
" cameras=cameras,\n",
- " controllers=controllers\n",
+ " controller_ids=controller_ids\n",
")\n",
"\n",
"for subplot in grid_plot:\n",
@@ -163,15 +163,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "fb49930f-b795-4b41-bbc6-014a27c2f463",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7d8aac54-4f36-41d4-8e5b-8d8da2f0d17d",
+ "id": "a18e7a17-c2af-4674-a499-bf5f3b27c8ca",
"metadata": {},
"outputs": [],
"source": []
diff --git a/examples/notebooks/scatter_sizes_animation.ipynb b/examples/notebooks/scatter_sizes_animation.ipynb
index 061f444d6..06a6b11a2 100644
--- a/examples/notebooks/scatter_sizes_animation.ipynb
+++ b/examples/notebooks/scatter_sizes_animation.ipynb
@@ -2,9 +2,39 @@
"cells": [
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "5d9f9913391a42af95d4d43d07c17b19",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "RFBOutputContext()"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "9cd08c319b814934a09fd266a1b6322b",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "JupyterOutputContext(children=(JupyterWgpuCanvas(), IpywidgetToolBar(children=(Button(icon='expand-arrows-alt'…"
+ ]
+ },
+ "execution_count": 1,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"from time import time\n",
"\n",
@@ -21,8 +51,6 @@
" current_time = time()\n",
" newPositions = points + np.sin(((current_time / 4) % 1)*np.pi)\n",
" plot.graphics[0].data = newPositions\n",
- " plot.camera.width = 4*np.max(newPositions[0,:])\n",
- " plot.camera.height = 4*np.max(newPositions[1,:])\n",
"\n",
"def update_sizes():\n",
" current_time = time()\n",
@@ -30,12 +58,11 @@
" size_delta = sin_sample*size_delta_scales\n",
" plot.graphics[0].sizes = min_sizes + size_delta\n",
"\n",
- "points = np.array([[0,0], \n",
- " [1,1], \n",
- " [2,2]])\n",
"scatter = plot.add_scatter(points, colors=[\"red\", \"green\", \"blue\"], sizes=12)\n",
"plot.add_animations(update_positions, update_sizes)\n",
- "plot.show(autoscale=True)"
+ "\n",
+ "plot.camera.width = 12\n",
+ "plot.show(autoscale=False)"
]
},
{
@@ -48,7 +75,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "fastplotlib-dev",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -62,10 +89,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.4"
- },
- "orig_nbformat": 4
+ "version": "3.11.3"
+ }
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/examples/notebooks/scatter_sizes_grid.ipynb b/examples/notebooks/scatter_sizes_grid.ipynb
index ff64184f7..e152056c9 100644
--- a/examples/notebooks/scatter_sizes_grid.ipynb
+++ b/examples/notebooks/scatter_sizes_grid.ipynb
@@ -19,15 +19,6 @@
"# grid with 2 rows and 3 columns\n",
"grid_shape = (2,1)\n",
"\n",
- "# pan-zoom controllers for each view\n",
- "# views are synced if they have the \n",
- "# same controller ID\n",
- "controllers = [\n",
- " [0],\n",
- " [0]\n",
- "]\n",
- "\n",
- "\n",
"# you can give string names for each subplot within the gridplot\n",
"names = [\n",
" [\"scalar_size\"],\n",
@@ -37,7 +28,6 @@
"# Create the grid plot\n",
"plot = fpl.GridPlot(\n",
" shape=grid_shape,\n",
- " controllers=controllers,\n",
" names=names,\n",
" size=(1000, 1000)\n",
")\n",
@@ -59,11 +49,18 @@
"\n",
"plot.show()"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
}
],
"metadata": {
"kernelspec": {
- "display_name": "fastplotlib-dev",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -77,10 +74,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.4"
- },
- "orig_nbformat": 4
+ "version": "3.11.3"
+ }
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/examples/notebooks/screenshots/nb-astronaut.png b/examples/notebooks/screenshots/nb-astronaut.png
index e8345f7b2..2faf79def 100644
--- a/examples/notebooks/screenshots/nb-astronaut.png
+++ b/examples/notebooks/screenshots/nb-astronaut.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:36a11f5c0a80e1cfbdeb318b314886f4d8e02ba8a763bed0db9994ef451bfd42
-size 128068
+oid sha256:4845a61b99f7a489ac82a8688cc3350ce66e4771bb1399354591fd39688a58a2
+size 127977
diff --git a/examples/notebooks/screenshots/nb-astronaut_RGB.png b/examples/notebooks/screenshots/nb-astronaut_RGB.png
index 0ff257ccf..22b2627cb 100644
--- a/examples/notebooks/screenshots/nb-astronaut_RGB.png
+++ b/examples/notebooks/screenshots/nb-astronaut_RGB.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:dc27fc081b464bb53afd98d3748b8bc75764537d76a8012b9f1b2c1d4c10613d
-size 125492
+oid sha256:2c34bd21fd7bf98bab25431019e8fee30b0f4912b6b4495ad963fb9e107b1f21
+size 125479
diff --git a/examples/notebooks/screenshots/nb-camera.png b/examples/notebooks/screenshots/nb-camera.png
index cbf936192..32e83f3ba 100644
--- a/examples/notebooks/screenshots/nb-camera.png
+++ b/examples/notebooks/screenshots/nb-camera.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cbf213d944a16cf9f72542e7a2172330fefa97c8577905f07df12559eb4485c3
-size 89303
+oid sha256:8ce695e954332a9b9122d418645d785900506fc30a897844bdf7fdce0bffb316
+size 89342
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-set_data.png b/examples/notebooks/screenshots/nb-image-widget-movie-set_data.png
new file mode 100644
index 000000000..61c3aeb8c
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-set_data.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:60318615e4850d37a4ffae16ca1e3bbf2985ddafd0dd65ba6fae997e1d123d67
+size 31251
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-0-reset.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-0-reset.png
new file mode 100644
index 000000000..d09ce18e4
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-0-reset.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6b9187c64b7439f629a87a3828cc46a855e1b4609eca52d5484223d2c24e8bf7
+size 62562
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-0.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-0.png
new file mode 100644
index 000000000..d09ce18e4
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6b9187c64b7439f629a87a3828cc46a855e1b4609eca52d5484223d2c24e8bf7
+size 62562
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-279.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-279.png
new file mode 100644
index 000000000..d4c299683
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-279.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:11eb83e3489a8e9c55fcffb0e67f1cf773e538629ddf98e109601749927caa56
+size 72525
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-max-33.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-max-33.png
new file mode 100644
index 000000000..ef5db6693
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-max-33.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:51bc6a90fba5c67935838b8e44dca477e250cbc4ee2b98ddd69f931e683ec17a
+size 63906
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-13.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-13.png
new file mode 100644
index 000000000..86287ea9e
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1a2318ab1f242d70045b9784337e4421c635b2345331b6a5e8edc0f32ff15f07
+size 54432
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-33.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-33.png
new file mode 100644
index 000000000..14c101960
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-33.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6c5b5df5b0efb0b3b641129e08429e4a92bd5d2c62b1c63c97337287867d685e
+size 50341
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-reset.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-reset.png
new file mode 100644
index 000000000..0df0df92b
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-reset.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f2e5a5734992333165ef2d5f6f810d869e157e59fb7f54c8dd5f413ac750a3fa
+size 65067
diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-50.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-50.png
new file mode 100644
index 000000000..0df0df92b
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-50.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f2e5a5734992333165ef2d5f6f810d869e157e59fb7f54c8dd5f413ac750a3fa
+size 65067
diff --git a/examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png b/examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png
new file mode 100644
index 000000000..da3033219
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:10912f4358278fb26c5efa030a335b0bdb80ebcc2a57fd97838fea3780f9f5d1
+size 143543
diff --git a/examples/notebooks/screenshots/nb-image-widget-single.png b/examples/notebooks/screenshots/nb-image-widget-single.png
new file mode 100644
index 000000000..346c1a987
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-single.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bf23c969c93bc526244360af4babf72a1377a171f55b1f44443dc026faf12631
+size 134432
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-gaussian.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-gaussian.png
new file mode 100644
index 000000000..6be1058e9
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-gaussian.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:49b65e35bb12e0bce8e753f6700084b2e1100eb6efd0336afc219d9e26972901
+size 64206
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-reset.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-reset.png
new file mode 100644
index 000000000..ead51e894
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-reset.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:df13f86bb18ad52f962f8944cd780579440b4e1d40941019632d4f46a4d9dc2d
+size 50107
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-max-window-13.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-max-window-13.png
new file mode 100644
index 000000000..295180169
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-max-window-13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:42676358a0199022972b69263c32a977f90a27ce6c3789d18129c67e9b730679
+size 121369
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-13.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-13.png
new file mode 100644
index 000000000..adf129ab2
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f3d1972c575f1659fc2c611a2c703cb408b74ca47e30c2e4564641dc0a6ad887
+size 76550
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-5.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-5.png
new file mode 100644
index 000000000..f123f83a9
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e24ea022d48ff41174206e43da911632f38237f6250340f73a7169a43d55f2a6
+size 72238
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png
new file mode 100644
index 000000000..8c65f7840
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:983cf6804561b4287f6acfdac04e2a31810c9d3191108e2da4623cbb852258d5
+size 56707
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png
new file mode 100644
index 000000000..fdc616d07
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4e6f528bf9508397a97e33d463ccd8b3584d3ebd04499b976b4989e001648626
+size 45174
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-gaussian.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-gaussian.png
new file mode 100644
index 000000000..66d5557ee
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-gaussian.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:69f8a085b84ee851ad1579791ff96fe6bc73551d86f376524d1194c43edf819f
+size 74941
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-reset.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-reset.png
new file mode 100644
index 000000000..3f53f463b
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-reset.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0616c08a8cf008fbc976638cfb7d76d533547bdb6cbfa56071567dac3c7e703d
+size 75619
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-max-window-13.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-max-window-13.png
new file mode 100644
index 000000000..e2f0161b7
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-max-window-13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e4f7893445c9f2d26f126a5ac87c1fdf0737b31fec730f754ba4c771eae5ec5b
+size 116744
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-13.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-13.png
new file mode 100644
index 000000000..fde3c576b
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a73e0ef31acf4304bc9a649f0761e0d282eb4517ade89538edfe6b7d8a9b61d0
+size 75487
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-5.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-5.png
new file mode 100644
index 000000000..c100dcaf3
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:00ade44cd4478bf77e7bd33ccee64e2905136e35620171f013be7e90ddaa0ba6
+size 79123
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50.png
new file mode 100644
index 000000000..08b244755
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1eb4d6a4cfbdbfffc198dbe5987f621e5cc3fdcf574699c544a12cf3b28bcdb7
+size 82281
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-99.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-99.png
new file mode 100644
index 000000000..6868bf1ff
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-99.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:758c4f444ab3792c6328e51d619c51f59f27fe2589795cc82bdef7fb5daf57e3
+size 79663
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-init-mean-window-5.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-init-mean-window-5.png
new file mode 100644
index 000000000..3bcfe6c24
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-init-mean-window-5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b75c179afde357fd69d7c3e918ad34e072685c536e388b1424596bd493b041e8
+size 81563
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-false.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-false.png
new file mode 100644
index 000000000..4a8ee413a
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-false.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e6d9460835d55d696ffcef1bff7cb7a86672d4c7345112c62050312669055870
+size 66010
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-true.png b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-true.png
new file mode 100644
index 000000000..984f1537c
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-true.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7b83f6353ce227d76fbf7362218bcc35afa26216e5600cf145cbcce666bb6dd6
+size 66520
diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-init-mean-window-5.png b/examples/notebooks/screenshots/nb-image-widget-zfish-init-mean-window-5.png
new file mode 100644
index 000000000..2767f8699
--- /dev/null
+++ b/examples/notebooks/screenshots/nb-image-widget-zfish-init-mean-window-5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:130c7a58ceee6ffe0ec58f194bce04e6f0892c97448b43ef9f90ced85c9c10ba
+size 62566
diff --git a/examples/notebooks/screenshots/nb-lines-3d.png b/examples/notebooks/screenshots/nb-lines-3d.png
index 6bb05537a..727450428 100644
--- a/examples/notebooks/screenshots/nb-lines-3d.png
+++ b/examples/notebooks/screenshots/nb-lines-3d.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b7e61fb22db10e515a7d249649c5e220731c6ea5a83bb626f06dcf41167f117e
-size 23052
+oid sha256:1da691b87d324d1a5b2c4f9231be89c0c3dddb0584615a07f28a4d027dc59d5c
+size 23057
diff --git a/examples/notebooks/screenshots/nb-lines-cmap-jet-values-cosine.png b/examples/notebooks/screenshots/nb-lines-cmap-jet-values-cosine.png
index b1045cde6..2f149e7f4 100644
--- a/examples/notebooks/screenshots/nb-lines-cmap-jet-values-cosine.png
+++ b/examples/notebooks/screenshots/nb-lines-cmap-jet-values-cosine.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1f55806e64a8ffde2f11eed1dc75a874371800046c062da21e71554abedda251
-size 17136
+oid sha256:a755f36126b805b8d63d6ea679ffa270dc20d976a9a3a2cd1420ccdf0e981474
+size 17158
diff --git a/examples/notebooks/screenshots/nb-lines-cmap-jet-values.png b/examples/notebooks/screenshots/nb-lines-cmap-jet-values.png
index 53b3d4cbd..45a34c5f0 100644
--- a/examples/notebooks/screenshots/nb-lines-cmap-jet-values.png
+++ b/examples/notebooks/screenshots/nb-lines-cmap-jet-values.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e5e9bcb785fe5efee324bdde451d62158668dafa0c026179bd11d38298fb0002
-size 18526
+oid sha256:76e55108ce7ace466fb9b90b852a1102ff8b4c931e16f05af231a854519c8467
+size 18505
diff --git a/examples/notebooks/screenshots/nb-lines-cmap-jet.png b/examples/notebooks/screenshots/nb-lines-cmap-jet.png
index 8bfd0d577..ed8138ab1 100644
--- a/examples/notebooks/screenshots/nb-lines-cmap-jet.png
+++ b/examples/notebooks/screenshots/nb-lines-cmap-jet.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2d6fd17a9a704b2d9c5341e85763f1ba9c5e3026da88858f004e66a781e02eaa
-size 16310
+oid sha256:7e463ac93808329ffa4fe421838ff8d39ce49081b888d09954405cd170af8a85
+size 16267
diff --git a/examples/notebooks/screenshots/nb-lines-cmap-tab-10.png b/examples/notebooks/screenshots/nb-lines-cmap-tab-10.png
index 3e76883bf..e10d6f5e9 100644
--- a/examples/notebooks/screenshots/nb-lines-cmap-tab-10.png
+++ b/examples/notebooks/screenshots/nb-lines-cmap-tab-10.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:672da2cc5e500ce3bbdabb01eaf5a7d2b9fb6ea4e6e95cb3392b2a0573a970d9
-size 14882
+oid sha256:99c10da11e298d69cd85d587b133fe31a5528657ba456e5f0050ca0e48ed0f31
+size 14865
diff --git a/examples/notebooks/screenshots/nb-lines-cmap-viridis-values.png b/examples/notebooks/screenshots/nb-lines-cmap-viridis-values.png
index 4b6212a6a..da5693226 100644
--- a/examples/notebooks/screenshots/nb-lines-cmap-viridis-values.png
+++ b/examples/notebooks/screenshots/nb-lines-cmap-viridis-values.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1e1224f75ce0286c4721b5f65af339fc922dcb2308f8d2fa3def10ead48cdce8
-size 15096
+oid sha256:d356938c29834263d9879c3217782414d631e998ea02f11f3c00c0f64d8a63a6
+size 15084
diff --git a/examples/notebooks/screenshots/nb-lines-cmap-viridis.png b/examples/notebooks/screenshots/nb-lines-cmap-viridis.png
index 35c38c881..ddcb6d54a 100644
--- a/examples/notebooks/screenshots/nb-lines-cmap-viridis.png
+++ b/examples/notebooks/screenshots/nb-lines-cmap-viridis.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f6201cd8dc9273adca73329b0eae81faf6aed42c3bf8f7ee503b9251af499dcd
-size 19203
+oid sha256:dfd17b5b191edf58377451b0c34636d047f69de1a89087d9d2d561d967c4d236
+size 19118
diff --git a/examples/notebooks/screenshots/nb-lines-cmap-white.png b/examples/notebooks/screenshots/nb-lines-cmap-white.png
index 67c2fc116..93efe221c 100644
--- a/examples/notebooks/screenshots/nb-lines-cmap-white.png
+++ b/examples/notebooks/screenshots/nb-lines-cmap-white.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ecb2d4d591b852bda8758efcf91d389442f916bbb4a06c5216d52dcf72172370
-size 12955
+oid sha256:d3b512a195ab30075a028d19884716c5f776acd6f118e682046d6659d1e1095e
+size 12962
diff --git a/examples/notebooks/screenshots/nb-lines-colors.png b/examples/notebooks/screenshots/nb-lines-colors.png
index b9972c8f4..a8af1a4be 100644
--- a/examples/notebooks/screenshots/nb-lines-colors.png
+++ b/examples/notebooks/screenshots/nb-lines-colors.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a8eefa5106414bfb540b282d74372831ef3c4a9d941aaf50026ea64a3d3009f7
-size 40544
+oid sha256:c8db3d4ccb1e56919866a6ba510033dc903d23a5af06a961f90ddb7382d16ec7
+size 40477
diff --git a/examples/notebooks/screenshots/nb-lines-data.png b/examples/notebooks/screenshots/nb-lines-data.png
index 14d6f89f0..369a999b2 100644
--- a/examples/notebooks/screenshots/nb-lines-data.png
+++ b/examples/notebooks/screenshots/nb-lines-data.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8e89906d0d749f443e751eeb43b017622a46dfaa91545e9135d0a519e0aad0eb
-size 54446
+oid sha256:2907942f9307eb21764ea02d363a8c6c8b7e4fbf375257b7c19225e1f7b66279
+size 54404
diff --git a/examples/notebooks/screenshots/nb-lines-underlay.png b/examples/notebooks/screenshots/nb-lines-underlay.png
index d8809f301..d6b630362 100644
--- a/examples/notebooks/screenshots/nb-lines-underlay.png
+++ b/examples/notebooks/screenshots/nb-lines-underlay.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:61ed6bde5639d57694cb8752052dda08a5f2f7dcc32966ab62385bc866c299e3
-size 55936
+oid sha256:70800d1739bb5ba7d5d9d2399335ebc1ce8a0874042ed4b6256b6d041014eb18
+size 55884
diff --git a/examples/notebooks/screenshots/nb-lines.png b/examples/notebooks/screenshots/nb-lines.png
index 3dcc1767e..2fcd0637f 100644
--- a/examples/notebooks/screenshots/nb-lines.png
+++ b/examples/notebooks/screenshots/nb-lines.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:39478dbf9af2f74ae0e0240616d94480569d53dcbd5f046315eeff3855d4cb2e
-size 37711
+oid sha256:4f70a9dd8cc631337ba1ccc7931ef2d412d0d6713d5403011994d59258f61e34
+size 37714
diff --git a/examples/notebooks/simple.ipynb b/examples/notebooks/simple.ipynb
index 681980d39..f5901080b 100644
--- a/examples/notebooks/simple.ipynb
+++ b/examples/notebooks/simple.ipynb
@@ -100,7 +100,7 @@
"image_graphic = plot.add_image(data=data, name=\"sample-image\")\n",
"\n",
"# show the plot\n",
- "plot.show()"
+ "plot.show(sidecar=True)"
]
},
{
@@ -589,7 +589,7 @@
"\n",
"plot_sync.add_animations(update_data_2)\n",
"\n",
- "plot_sync.show(sidecar=False)"
+ "plot_sync.show()"
]
},
{
@@ -704,7 +704,7 @@
"sinc_graphic = plot_l.add_line(data=sinc, thickness=5, colors = colors)\n",
"\n",
"# show the plot\n",
- "plot_l.show(sidecar_kwargs={\"title\": \"lines\", \"layout\": {'width': '800px'}})"
+ "plot_l.show(sidecar=True, sidecar_kwargs={\"title\": \"lines\"})"
]
},
{
@@ -1020,6 +1020,14 @@
"plot_l3d.show()"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "29f07af0-cdcb-47cc-bbb3-2fa4449fa084",
+ "metadata": {},
+ "source": [
+ "**Use WASD keys and the mouse to move around, just like in a game :D. Use the mouse weel to control the speed of movement.**"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -1045,6 +1053,17 @@
"plot_test(\"lines-3d\", plot_l3d)"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7a6da884-8b40-4ebf-837f-929b3e9cf4c4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# change the FOV of the persepctive camera\n",
+ "plot_l3d.camera.fov = 70"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -1187,6 +1206,25 @@
"scatter_graphic.data[n_points:n_points * 2, 0] = np.linspace(-40, 0, n_points)"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "5f3e206d-97af-4e07-9969-94f2fdb41004",
+ "metadata": {},
+ "source": [
+ "**Switch to a fly controller to move around the plot in 3D!**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c67944ca-52e7-4213-b820-6572cc3f76f0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_s.camera = \"3d\"\n",
+ "plot_s.controller = \"fly\""
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
diff --git a/examples/notebooks/zfish_test.npy b/examples/notebooks/zfish_test.npy
new file mode 100644
index 000000000..61f0474e6
--- /dev/null
+++ b/examples/notebooks/zfish_test.npy
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ff73fdbde34cafaf01254b9e72bdc484d865e6c3288ef88fc1953f349fc02152
+size 26214528
diff --git a/fastplotlib/VERSION b/fastplotlib/VERSION
index a0ad4fd5d..d9958b371 100644
--- a/fastplotlib/VERSION
+++ b/fastplotlib/VERSION
@@ -1 +1 @@
-0.1.0.a15
+0.1.0.a16
diff --git a/fastplotlib/layouts/_defaults.py b/fastplotlib/layouts/_defaults.py
index 9a223855f..b28b04f64 100644
--- a/fastplotlib/layouts/_defaults.py
+++ b/fastplotlib/layouts/_defaults.py
@@ -1,46 +1,3 @@
-import pygfx
-from typing import *
-camera_types = {
- "2d": pygfx.OrthographicCamera,
- "3d": pygfx.PerspectiveCamera,
-}
-controller_types = {
- "2d": pygfx.PanZoomController,
- "3d": pygfx.OrbitController,
- pygfx.OrthographicCamera: pygfx.PanZoomController,
- pygfx.PerspectiveCamera: pygfx.OrbitController,
-}
-
-def create_camera(
- camera_type: str, big_camera: bool = False
-) -> Union[pygfx.OrthographicCamera, pygfx.PerspectiveCamera]:
- camera_type = camera_type.split("-")
-
- # kinda messy but works for now
- if len(camera_type) > 1:
- if camera_type[1] == "big":
- big_camera = True
-
- camera_type = camera_type[0]
- else:
- camera_type = camera_type[0]
-
- cls = camera_types[camera_type]
-
- if cls is pygfx.OrthographicCamera:
- if big_camera:
- return cls(1024, 1024, -8192, 8192)
- else:
- return cls(1024, 1024)
-
- else:
- return cls()
-
-
-def create_controller(controller_type: str):
- controller_type = controller_type.split("-")[0]
-
- return controller_types[controller_type]()
diff --git a/fastplotlib/layouts/_gridplot.py b/fastplotlib/layouts/_gridplot.py
index 473196f78..459aca5fd 100644
--- a/fastplotlib/layouts/_gridplot.py
+++ b/fastplotlib/layouts/_gridplot.py
@@ -1,4 +1,4 @@
-from itertools import product
+from itertools import product, chain
import numpy as np
from typing import *
from inspect import getfullargspec
@@ -9,8 +9,8 @@
from wgpu.gui.auto import WgpuCanvas
from ._frame import Frame
-from ._utils import make_canvas_and_renderer
-from ._defaults import create_controller
+from ._utils import make_canvas_and_renderer, create_controller, create_camera
+from ._utils import controller_types as valid_controller_types
from ._subplot import Subplot
from ._record_mixin import RecordMixin
@@ -25,43 +25,47 @@ def to_array(a) -> np.ndarray:
return np.array(a)
-valid_cameras = ["2d", "2d-big", "3d", "3d-big"]
-
-
class GridPlot(Frame, RecordMixin):
def __init__(
self,
shape: Tuple[int, int],
- cameras: Union[np.ndarray, str] = "2d",
- controllers: Union[np.ndarray, str] = None,
+ cameras: Union[str, list, np.ndarray] = "2d",
+ controller_types: Union[str, list, np.ndarray] = None,
+ controller_ids: Union[str, list, np.ndarray] = None,
canvas: Union[str, WgpuCanvas, pygfx.Texture] = None,
renderer: pygfx.WgpuRenderer = None,
size: Tuple[int, int] = (500, 300),
- **kwargs,
+ names: Union[list, np.ndarray] = None,
):
"""
A grid of subplots.
Parameters
----------
- shape: tuple of int
+ shape: (int, int)
(n_rows, n_cols)
- cameras: np.ndarray or str, optional
+ cameras: str, list, or np.ndarray, optional
| One of ``"2d"`` or ``"3d"`` indicating 2D or 3D cameras for all subplots
- | OR
- | Array of ``2d`` and/or ``3d`` that specifies the camera type for each subplot
+ | list/array of ``2d`` and/or ``3d`` that specifies the camera type for each subplot
+ | list/array of pygfx.PerspectiveCamera instances
+
+ controller_types: str, list or np.ndarray, optional
+ list or array that specifies the controller type for each subplot, or list/array of
+ pygfx.Controller instances
- controllers: np.ndarray or str, optional
+ controller_ids: str, list or np.ndarray of int or str ids, optional
| If `None` a unique controller is created for each subplot
| If "sync" all the subplots use the same controller
| If ``numpy.array``, its shape must be the same as ``grid_shape``.
This allows custom assignment of controllers
- | Example:
- | unique controllers for a 2x2 gridplot: np.array([[0, 1], [2, 3]])
- | same controllers for first 2 plots and last 2 plots: np.array([[0, 0, 1], [2, 3, 3]])
+ | Example with integers:
+ | sync first 2 plots, and sync last 2 plots: [[0, 0, 1], [2, 3, 3]]
+ | Example with str subplot names:
+ | list of lists of subplot names, each sublist is synced: [[subplot_a, subplot_b], [subplot_f, subplot_c]]
+ | this syncs subplot_a and subplot_b together; syncs subplot_f and subplot_c together
canvas: WgpuCanvas, optional
Canvas for drawing
@@ -69,70 +73,147 @@ def __init__(
renderer: pygfx.Renderer, optional
pygfx renderer instance
- size: (int, int)
+ size: (int, int), optional
starting size of canvas, default (500, 300)
+ names: list or array of str, optional
+ subplot names
"""
self.shape = shape
+ if names is not None:
+ if len(list(chain(*names))) != self.shape[0] * self.shape[1]:
+ raise ValueError("must provide same number of subplot `names` as specified by gridplot shape")
+
+ self.names = to_array(names).reshape(self.shape)
+ else:
+ self.names = None
+
canvas, renderer = make_canvas_and_renderer(canvas, renderer)
if isinstance(cameras, str):
- if cameras not in valid_cameras:
- raise ValueError(
- f"If passing a str, `cameras` must be one of: {valid_cameras}"
- )
# create the array representing the views for each subplot in the grid
cameras = np.array([cameras] * self.shape[0] * self.shape[1]).reshape(
self.shape
)
- if isinstance(controllers, str):
- if controllers == "sync":
- controllers = np.zeros(
- self.shape[0] * self.shape[1], dtype=int
- ).reshape(self.shape)
+ # list -> array if necessary
+ cameras = to_array(cameras).reshape(self.shape)
- if controllers is None:
- controllers = np.arange(self.shape[0] * self.shape[1]).reshape(self.shape)
+ if cameras.shape != self.shape:
+ raise ValueError("Number of cameras does not match the number of subplots")
- controllers = to_array(controllers)
+ # create the cameras
+ self._cameras = np.empty(self.shape, dtype=object)
+ for i, j in product(range(self.shape[0]), range(self.shape[1])):
+ self._cameras[i, j] = create_camera(camera_type=cameras[i, j])
- if controllers.shape != self.shape:
- raise ValueError
+ if controller_ids is None:
+ # individual controller for each subplot
+ controller_ids = np.arange(self.shape[0] * self.shape[1]).reshape(self.shape)
- cameras = to_array(cameras)
+ elif isinstance(controller_ids, str):
+ if controller_ids == "sync":
+ controller_ids = np.zeros(self.shape, dtype=int)
+ else:
+ raise ValueError(
+ f"`controller_ids` must be one of 'sync', an array/list of subplot names, or an array/list of "
+ f"integer ids. See the docstring for more details."
+ )
- self._controllers = np.empty(shape=cameras.shape, dtype=object)
+ # list controller_ids
+ elif isinstance(controller_ids, (list, np.ndarray)):
+ ids_flat = list(chain(*controller_ids))
- if cameras.shape != self.shape:
- raise ValueError
-
- # create controllers if the arguments were integers
- if np.issubdtype(controllers.dtype, np.integer):
- if not np.all(
- np.sort(np.unique(controllers))
- == np.arange(np.unique(controllers).size)
- ):
- raise ValueError("controllers must be consecutive integers")
-
- for controller in np.unique(controllers):
- cam = np.unique(cameras[controllers == controller])
- if cam.size > 1:
+ # list of str of subplot names, convert this to integer ids
+ if all([isinstance(item, str) for item in ids_flat]):
+ if self.names is None:
+ raise ValueError("must specify subplot `names` to use list of str for `controller_ids`")
+
+ # make sure each controller_id str is a subplot name
+ if not all([n in self.names for n in ids_flat]):
+ raise KeyError(
+ f"all `controller_ids` strings must be one of the subplot names"
+ )
+
+ if len(ids_flat) > len(set(ids_flat)):
raise ValueError(
- f"Controller id: {controller} has been assigned to multiple different camera types"
+ "id strings must not appear twice in `controller_ids`"
)
- self._controllers[controllers == controller] = create_controller(cam[0])
- # else assume it's a single pygfx.Controller instance or a list of controllers
- else:
- if isinstance(controllers, pygfx.Controller):
- self._controllers = np.array(
- [controllers] * shape[0] * shape[1]
- ).reshape(shape)
+ # initialize controller_ids array
+ ids_init = np.arange(self.shape[0] * self.shape[1]).reshape(self.shape)
+
+ # set id based on subplot position for each synced sublist
+ for i, sublist in enumerate(controller_ids):
+ for name in sublist:
+ ids_init[self.names == name] = -(i + 1) # use negative numbers because why not
+
+ controller_ids = ids_init
+
+ # integer ids
+ elif all([isinstance(item, (int, np.integer)) for item in ids_flat]):
+ controller_ids = to_array(controller_ids).reshape(self.shape)
+
else:
- self._controllers = np.array(controllers).reshape(shape)
+ raise TypeError(
+ f"list argument to `controller_ids` must be a list of `str` or `int`, "
+ f"you have passed: {controller_ids}"
+ )
+
+ if controller_ids.shape != self.shape:
+ raise ValueError("Number of controller_ids does not match the number of subplots")
+
+ if controller_types is None:
+ # `create_controller()` will auto-determine controller for each subplot based on defaults
+ controller_types = np.array(["default"] * self.shape[0] * self.shape[1]).reshape(self.shape)
+
+ # validate controller types
+ types_flat = list(chain(*controller_types))
+ # str controller_type or pygfx instances
+ valid_str = list(valid_controller_types.keys()) + ["default"]
+ valid_instances = tuple(valid_controller_types.values())
+
+ # make sure each controller type is valid
+ for controller_type in types_flat:
+ if controller_type is None:
+ continue
+
+ if (controller_type not in valid_str) and (not isinstance(controller_type, valid_instances)):
+ raise ValueError(
+ f"You have passed an invalid controller type, valid controller_types arguments are:\n"
+ f"{valid_str} or instances of {[c.__name__ for c in valid_instances]}"
+ )
+
+ controller_types = to_array(controller_types).reshape(self.shape)
+
+ # make the real controllers for each subplot
+ self._controllers = np.empty(shape=self.shape, dtype=object)
+ for cid in np.unique(controller_ids):
+ cont_type = controller_types[controller_ids == cid]
+ if np.unique(cont_type).size > 1:
+ raise ValueError(
+ "Multiple controller types have been assigned to the same controller id. "
+ "All controllers with the same id must use the same type of controller."
+ )
+
+ cont_type = cont_type[0]
+
+ # get all the cameras that use this controller
+ cams = self._cameras[controller_ids == cid].ravel()
+
+ if cont_type == "default":
+ # hacky fix for now because of how `create_controller()` works
+ cont_type = None
+ _controller = create_controller(controller_type=cont_type, camera=cams[0])
+
+ self._controllers[controller_ids == cid] = _controller
+
+ # add the other cameras that go with this controller
+ if cams.size > 1:
+ for cam in cams[1:]:
+ _controller.add_camera(cam)
if canvas is None:
canvas = WgpuCanvas()
@@ -140,13 +221,6 @@ def __init__(
if renderer is None:
renderer = pygfx.renderers.WgpuRenderer(canvas)
- if "names" in kwargs.keys():
- self.names = to_array(kwargs["names"])
- if self.names.shape != self.shape:
- raise ValueError
- else:
- self.names = None
-
self._canvas = canvas
self._renderer = renderer
@@ -158,7 +232,7 @@ def __init__(
for i, j in self._get_iterator():
position = (i, j)
- camera = cameras[i, j]
+ camera = self._cameras[i, j]
controller = self._controllers[i, j]
if self.names is not None:
@@ -304,5 +378,15 @@ def __next__(self) -> Subplot:
pos = self._current_iter.__next__()
return self._subplots[pos]
+ def __str__(self):
+ return f"{self.__class__.__name__} @ {hex(id(self))}"
+
def __repr__(self):
- return f"fastplotlib.{self.__class__.__name__} @ {hex(id(self))}\n"
+ newline = "\n\t"
+
+ return (
+ f"fastplotlib.{self.__class__.__name__} @ {hex(id(self))}\n"
+ f" Subplots:\n"
+ f"\t{newline.join(subplot.__str__() for subplot in self)}"
+ f"\n"
+ )
diff --git a/fastplotlib/layouts/_plot.py b/fastplotlib/layouts/_plot.py
index 5aa04bb76..34027a276 100644
--- a/fastplotlib/layouts/_plot.py
+++ b/fastplotlib/layouts/_plot.py
@@ -11,10 +11,10 @@
class Plot(Subplot, Frame, RecordMixin):
def __init__(
self,
- canvas: WgpuCanvas = None,
+ canvas: Union[str, WgpuCanvas] = None,
renderer: pygfx.WgpuRenderer = None,
- camera: str = "2d",
- controller: Union[pygfx.PanZoomController, pygfx.OrbitController] = None,
+ camera: Union[str, pygfx.PerspectiveCamera] = "2d",
+ controller: Union[str, pygfx.Controller] = None,
size: Tuple[int, int] = (500, 300),
**kwargs,
):
@@ -29,12 +29,14 @@ def __init__(
renderer: pygfx.Renderer, optional
pygfx renderer instance
- camera:str, optional
+ camera: str or pygfx.PerspectiveCamera, optional
| One of ``"2d"`` or ``"3d"`` indicating 2D or 3D camera
- controller: None, PanZoomController or OrbitOrthoController, optional
+ controller: str or pygfx.Controller, optional
Usually ``None``, you can pass an existing controller from another
- ``Plot`` or ``Subplot`` within a ``GridPlot`` to synchronize them.
+ ``Plot`` or ``Subplot`` to synchronize them.
+
+ You can also pass str arguments of valid controller names, see Subplot docstring for valid names
size: (int, int)
starting size of canvas, default (500, 300)
diff --git a/fastplotlib/layouts/_plot_area.py b/fastplotlib/layouts/_plot_area.py
index 7590bad10..9522832d3 100644
--- a/fastplotlib/layouts/_plot_area.py
+++ b/fastplotlib/layouts/_plot_area.py
@@ -6,18 +6,10 @@
import numpy as np
import pygfx
-from pygfx import (
- Scene,
- OrthographicCamera,
- PerspectiveCamera,
- PanZoomController,
- OrbitController,
- Viewport,
- WgpuRenderer,
-)
from pylinalg import vec_transform, vec_unproject
from wgpu.gui.auto import WgpuCanvas
+from ._utils import create_camera, create_controller
from ..graphics._base import Graphic
from ..graphics.selectors._base_selector import BaseSelector
@@ -33,11 +25,11 @@ def __init__(
self,
parent,
position: Any,
- camera: Union[OrthographicCamera, PerspectiveCamera],
- controller: Union[PanZoomController, OrbitController],
- scene: Scene,
+ camera: Union[pygfx.PerspectiveCamera],
+ controller: Union[pygfx.Controller],
+ scene: pygfx.Scene,
canvas: WgpuCanvas,
- renderer: WgpuRenderer,
+ renderer: pygfx.WgpuRenderer,
name: str = None,
):
"""
@@ -53,25 +45,23 @@ def __init__(
typical use will be for ``subplots`` in a ``gridplot``, position would correspond to the ``[row, column]``
location of the ``subplot`` in its ``gridplot``
- camera: pygfx OrthographicCamera or pygfx PerspectiveCamera
- ``OrthographicCamera`` type is used to visualize 2D content and ``PerspectiveCamera`` type is used to view
- 3D content, used to view the scene
+ camera: pygfx.PerspectiveCamera
+ Use perspective camera for both perspective and orthographic views. Set fov = 0 for orthographic mode.
- controller: pygfx PanZoomController or pygfx OrbitController
- ``PanZoomController`` type is used for 2D pan-zoom camera control and ``OrbitController`` type is used for
- rotating the camera around a center position, used to control the camera
+ controller: pygfx.Controller
+ One of the pygfx controllers, panzoom, fly, orbit, or trackball
- scene: pygfx Scene
+ scene: pygfx.Scene
represents the root of a scene graph, will be viewed by the given ``camera``
canvas: WgpuCanvas
provides surface on which a scene will be rendered
- renderer: WgpuRenderer
- object used to render scenes using wgpu
+ renderer: pygfx.WgpuRenderer
+ renders the scene onto the canvas
name: str, optional
- name of ``subplot`` or ``plot`` subclass being instantiated
+ name this ``subplot`` or ``plot``
"""
@@ -82,14 +72,14 @@ def __init__(
self._canvas = canvas
self._renderer = renderer
if parent is None:
- self._viewport: Viewport = Viewport(renderer)
+ self._viewport: pygfx.Viewport = pygfx.Viewport(renderer)
else:
- self._viewport = Viewport(parent.renderer)
+ self._viewport = pygfx.Viewport(parent.renderer)
self._camera = camera
self._controller = controller
- self.controller.add_camera(self.camera)
+ self.controller.add_camera(self._camera)
self.controller.register_events(
self.viewport,
)
@@ -126,7 +116,7 @@ def position(self) -> Union[Tuple[int, int], Any]:
return self._position
@property
- def scene(self) -> Scene:
+ def scene(self) -> pygfx.Scene:
"""The Scene where Graphics lie in this plot area"""
return self._scene
@@ -136,26 +126,82 @@ def canvas(self) -> WgpuCanvas:
return self._canvas
@property
- def renderer(self) -> WgpuRenderer:
+ def renderer(self) -> pygfx.WgpuRenderer:
"""Renderer associated to the plot area"""
return self._renderer
@property
- def viewport(self) -> Viewport:
+ def viewport(self) -> pygfx.Viewport:
"""The rectangular area of the renderer associated to this plot area"""
return self._viewport
@property
- def camera(self) -> Union[OrthographicCamera, PerspectiveCamera]:
+ def camera(self) -> pygfx.PerspectiveCamera:
"""camera used to view the scene"""
return self._camera
+ @camera.setter
+ def camera(self, new_camera: Union[str, pygfx.PerspectiveCamera]):
+ # user wants to set completely new camera, remove current camera from controller
+ if isinstance(new_camera, pygfx.PerspectiveCamera):
+ self.controller.remove_camera(self._camera)
+ # add new camera to controller
+ self.controller.add_camera(new_camera)
+
+ self._camera = new_camera
+
+ # modify FOV if necessary
+ elif isinstance(new_camera, str):
+ if new_camera == "2d":
+ self._camera.fov = 0
+
+ elif new_camera == "3d":
+ # orthographic -> perspective only if fov = 0, i.e. if camera is in ortho mode
+ # otherwise keep same FOV
+ if self._camera.fov == 0:
+ self._camera.fov = 50
+
+ else:
+ raise ValueError("camera must be one of '2d', '3d' or a pygfx.PerspectiveCamera instance")
+ else:
+ raise ValueError("camera must be one of '2d', '3d' or a pygfx.PerspectiveCamera instance")
+
# in the future we can think about how to allow changing the controller
@property
- def controller(self) -> Union[PanZoomController, OrbitController]:
- """controller used to control camera"""
+ def controller(self) -> pygfx.Controller:
+ """controller used to control the camera"""
return self._controller
+ @controller.setter
+ def controller(self, new_controller: Union[str, pygfx.Controller]):
+ new_controller = create_controller(new_controller, self._camera)
+
+ cameras_list = list()
+
+ # remove all the cameras associated to this controller
+ for camera in self._controller.cameras:
+ self._controller.remove_camera(camera)
+ cameras_list.append(camera)
+
+ # add the associated cameras to the new controller
+ for camera in cameras_list:
+ new_controller.add_camera(camera)
+
+ new_controller.register_events(
+ self.viewport
+ )
+
+ # TODO: monkeypatch until we figure out a better
+ # pygfx plans on refactoring viewports anyways
+ if self.parent is not None:
+ if self.parent.__class__.__name__ == "GridPlot":
+ for subplot in self.parent:
+ if subplot.camera in cameras_list:
+ new_controller.register_events(subplot.viewport)
+ subplot._controller = new_controller
+
+ self._controller = new_controller
+
@property
def graphics(self) -> Tuple[Graphic, ...]:
"""Graphics in the plot area. Always returns a proxy to the Graphic instances."""
@@ -459,7 +505,7 @@ def center_graphic(self, graphic: Graphic, zoom: float = 1.35):
# probably because camera.show_object uses bounding sphere
self.camera.zoom = zoom
- def center_scene(self, zoom: float = 1.35):
+ def center_scene(self, *, zoom: float = 1.35):
"""
Auto-center the scene, does not scale.
@@ -481,15 +527,20 @@ def center_scene(self, zoom: float = 1.35):
# probably because camera.show_object uses bounding sphere
camera.zoom = zoom
- def auto_scale(self, maintain_aspect: bool = False, zoom: float = 0.8):
+ def auto_scale(
+ self,
+ *, # since this is often used as an event handler, don't want to coerce maintain_aspect = True
+ maintain_aspect: Union[None, bool] = None,
+ zoom: float = 0.8
+ ):
"""
Auto-scale the camera w.r.t to the scene
Parameters
----------
- maintain_aspect: bool, default ``False``
- maintain the camera aspect ratio for all dimensions, if ``False`` the camera
- is scaled according to the bounds in each dimension.
+ maintain_aspect: ``None`` or bool, default ``None``
+ Maintain the camera aspect ratio for all dimensions. If ``None``, the aspect is left unchanged.
+ if ``False`` the camera is scaled to the bounding box of the current scene.
zoom: float, default 0.8
zoom value for the camera after auto-scaling, if zoom = 1.0 then the graphics
@@ -503,8 +554,9 @@ def auto_scale(self, maintain_aspect: bool = False, zoom: float = 0.8):
self.scene.remove(selector.world_object)
self.center_scene()
- if not isinstance(maintain_aspect, bool):
- maintain_aspect = False # assume False
+
+ if maintain_aspect is None: # if not provided keep current setting
+ maintain_aspect = self.camera.maintain_aspect
# scale all cameras associated with this controller else it looks wonky
for camera in self.controller.cameras:
@@ -657,7 +709,7 @@ def __repr__(self):
return (
f"{self}\n"
- f" parent: {self.parent}\n"
+ f" parent: {self.parent.__str__()}\n"
f" Graphics:\n"
f"\t{newline.join(graphic.__repr__() for graphic in self.graphics)}"
f"\n"
diff --git a/fastplotlib/layouts/_subplot.py b/fastplotlib/layouts/_subplot.py
index c178c0fca..e9eae7603 100644
--- a/fastplotlib/layouts/_subplot.py
+++ b/fastplotlib/layouts/_subplot.py
@@ -2,22 +2,13 @@
import numpy as np
-from pygfx import (
- Scene,
- OrthographicCamera,
- PanZoomController,
- OrbitController,
- AxesHelper,
- GridHelper,
- WgpuRenderer,
- Texture,
-)
+import pygfx
+
from wgpu.gui.auto import WgpuCanvas
from ..graphics import TextGraphic
-from ._utils import make_canvas_and_renderer
+from ._utils import make_canvas_and_renderer, create_camera, create_controller
from ._plot_area import PlotArea
-from ._defaults import create_camera, create_controller
from .graphic_methods_mixin import GraphicMethodsMixin
@@ -27,12 +18,11 @@ def __init__(
parent: Any = None,
position: Tuple[int, int] = None,
parent_dims: Tuple[int, int] = None,
- camera: str = "2d",
- controller: Union[PanZoomController, OrbitController] = None,
- canvas: Union[str, WgpuCanvas, Texture] = None,
- renderer: WgpuRenderer = None,
+ camera: Union[str, pygfx.PerspectiveCamera] = "2d",
+ controller: Union[str, pygfx.Controller] = None,
+ canvas: Union[str, WgpuCanvas, pygfx.Texture] = None,
+ renderer: pygfx.WgpuRenderer = None,
name: str = None,
- **kwargs,
):
"""
General plot object that composes a ``Gridplot``. Each ``Gridplot`` instance will have [n rows, n columns]
@@ -43,21 +33,25 @@ def __init__(
Parameters
----------
- position: int tuple, optional
+ parent: Any
+ parent GridPlot instance
+
+ position: (int, int), optional
corresponds to the [row, column] position of the subplot within a ``Gridplot``
- parent_dims: int tuple, optional
+ parent_dims: (int, int), optional
dimensions of the parent ``GridPlot``
- camera: str, default '2d'
- indicates the kind of pygfx camera that will be instantiated, '2d' uses pygfx ``OrthographicCamera`` and
- '3d' uses pygfx ``PerspectiveCamera``
+ camera: str or pygfx.PerspectiveCamera, default '2d'
+ indicates the FOV for the camera, '2d' sets ``fov = 0``, '3d' sets ``fov = 50``.
+ ``fov`` can be changed at any time.
- controller: PanZoomController or OrbitOrthoController, optional
- ``PanZoomController`` type is used for 2D pan-zoom camera control and ``OrbitController`` type is used for
- rotating the camera around a center position, used to control the camera
+ controller: str or pygfx.Controller, optional
+ | if ``None``, uses a PanZoomController for "2d" camera or FlyController for "3d" camera.
+ | if ``str``, must be one of: `"panzoom", "fly", "trackball", or "orbit"`.
+ | also accepts a pygfx.Controller instance
- canvas: WgpuCanvas, Texture, or one of "jupyter", "glfw", "qt", optional
+ canvas: one of "jupyter", "glfw", "qt", WgpuCanvas, or pygfx.Texture, optional
Provides surface on which a scene will be rendered. Can optionally provide a WgpuCanvas instance or a str
to force the PlotArea to use a specific canvas from one of the following options: "jupyter", "glfw", "qt".
Can also provide a pygfx Texture to render to.
@@ -82,25 +76,26 @@ def __init__(
self.nrows, self.ncols = parent_dims
- if controller is None:
- controller = create_controller(camera)
+ camera = create_camera(camera)
+
+ controller = create_controller(controller_type=controller, camera=camera)
self._docks = dict()
self.spacing = 2
- self._axes: AxesHelper = AxesHelper(size=100)
+ self._axes: pygfx.AxesHelper = pygfx.AxesHelper(size=100)
for arrow in self._axes.children:
self._axes.remove(arrow)
- self._grid: GridHelper = GridHelper(size=100, thickness=1)
+ self._grid: pygfx.GridHelper = pygfx.GridHelper(size=100, thickness=1)
super(Subplot, self).__init__(
parent=parent,
position=position,
- camera=create_camera(camera),
+ camera=camera,
controller=controller,
- scene=Scene(),
+ scene=pygfx.Scene(),
canvas=canvas,
renderer=renderer,
name=name,
@@ -221,9 +216,9 @@ def __init__(
super(Dock, self).__init__(
parent=parent,
position=position,
- camera=OrthographicCamera(),
- controller=PanZoomController(),
- scene=Scene(),
+ camera=pygfx.OrthographicCamera(),
+ controller=pygfx.PanZoomController(),
+ scene=pygfx.Scene(),
canvas=parent.canvas,
renderer=parent.renderer,
)
diff --git a/fastplotlib/layouts/_utils.py b/fastplotlib/layouts/_utils.py
index dd6fbeb50..7db1d84c4 100644
--- a/fastplotlib/layouts/_utils.py
+++ b/fastplotlib/layouts/_utils.py
@@ -1,5 +1,6 @@
from typing import *
+import pygfx
from pygfx import WgpuRenderer, Texture
# default auto-determined canvas
@@ -66,7 +67,7 @@ def make_canvas_and_renderer(
if canvas is None:
Canvas = auto_determine_canvas()
- canvas = Canvas()
+ canvas = Canvas(max_fps=60)
elif isinstance(canvas, str):
if canvas not in CANVAS_OPTIONS:
@@ -76,7 +77,7 @@ def make_canvas_and_renderer(
f"The {canvas} framework is not installed for using this canvas"
)
else:
- canvas = CANVAS_OPTIONS_AVAILABLE[canvas]()
+ canvas = CANVAS_OPTIONS_AVAILABLE[canvas](max_fps=60)
elif not isinstance(canvas, (WgpuCanvasBase, Texture)):
raise ValueError(
@@ -88,3 +89,58 @@ def make_canvas_and_renderer(
renderer = WgpuRenderer(canvas)
return canvas, renderer
+
+
+def create_camera(
+ camera_type: Union[pygfx.PerspectiveCamera, str],
+) -> pygfx.PerspectiveCamera:
+ if isinstance(camera_type, pygfx.PerspectiveCamera):
+ return camera_type
+
+ elif camera_type == "2d":
+ # use perspective for orthographic, makes it easier to then switch to controllers that make sense with fov > 0
+ return pygfx.PerspectiveCamera(fov=0)
+
+ elif camera_type == "3d":
+ return pygfx.PerspectiveCamera()
+
+ else:
+ raise ValueError(
+ "camera must be one of: '2d', '3d' or an instance of pygfx.PerspectiveCamera"
+ )
+
+
+controller_types = {
+ "fly": pygfx.FlyController,
+ "panzoom": pygfx.PanZoomController,
+ "trackball": pygfx.TrackballController,
+ "orbit": pygfx.OrbitController,
+}
+
+
+def create_controller(
+ controller_type: Union[pygfx.Controller, None, str],
+ camera: pygfx.PerspectiveCamera,
+) -> pygfx.Controller:
+ """
+ Creates the controllers and adds the camera to it.
+ """
+ if isinstance(controller_type, pygfx.Controller):
+ controller_type.add_camera(camera)
+ return controller_type
+
+ if controller_type is None:
+ # default controllers
+ if camera.fov == 0:
+ # default for orthographic
+ return pygfx.PanZoomController(camera)
+ else:
+ return pygfx.FlyController(camera)
+
+ if controller_type not in controller_types.keys():
+ raise KeyError(
+ f"controller must be a valid pygfx.Controller or one of: "
+ f"{list(controller_types.keys())}, you have passed: {controller_type}"
+ )
+
+ return controller_types[controller_type](camera)
diff --git a/fastplotlib/widgets/histogram_lut.py b/fastplotlib/widgets/histogram_lut.py
index 0d8ca9f15..64feb8df6 100644
--- a/fastplotlib/widgets/histogram_lut.py
+++ b/fastplotlib/widgets/histogram_lut.py
@@ -180,7 +180,8 @@ def _calculate_histogram(self, data):
hist_scaled = hist_flanked / (hist_flanked.max() / 100)
if edges_flanked.size > hist_scaled.size:
- edges_flanked = edges_flanked[:-1]
+ # we don't care about accuracy here so if it's off by 1-2 bins that's fine
+ edges_flanked = edges_flanked[:hist_scaled.size]
return hist, edges, hist_scaled, edges_flanked
diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py
index da256207f..a3f6335c9 100644
--- a/fastplotlib/widgets/image.py
+++ b/fastplotlib/widgets/image.py
@@ -40,7 +40,8 @@ def _is_arraylike(obj) -> bool:
class _WindowFunctions:
"""Stores window function and window size"""
- def __init__(self, func: callable, window_size: int):
+ def __init__(self, image_widget, func: callable, window_size: int):
+ self._image_widget = image_widget
self._func = None
self.func = func
@@ -56,6 +57,9 @@ def func(self) -> callable:
def func(self, func: callable):
self._func = func
+ # force update
+ self._image_widget.current_index = self._image_widget.current_index
+
@property
def window_size(self) -> int:
"""Get or set window size"""
@@ -84,6 +88,8 @@ def window_size(self, ws: int):
self._window_size = ws
+ self._image_widget.current_index = self._image_widget.current_index
+
def __repr__(self):
return f"func: {self.func}, window_size: {self.window_size}"
@@ -101,7 +107,7 @@ def widget(self):
"""
Output context, either an ipywidget or QWidget
"""
- return self.gridplot.widget
+ return self._output
@property
def managed_graphics(self) -> List[ImageGraphic]:
@@ -185,6 +191,10 @@ def current_index(self) -> Dict[str, int]:
@current_index.setter
def current_index(self, index: Dict[str, int]):
+ # ignore if output context has not been created yet
+ if self.widget is None:
+ return
+
if not set(index.keys()).issubset(set(self._current_index.keys())):
raise KeyError(
f"All dimension keys for setting `current_index` must be present in the widget sliders. "
@@ -299,6 +309,9 @@ def __init__(
self._names = None
+ # output context
+ self._output = None
+
if isinstance(data, list):
# verify that it's a list of np.ndarray
if all([_is_arraylike(d) for d in data]):
@@ -494,14 +507,14 @@ def __init__(
f"`slider_dims` must a , or , you have passed a: {type(slider_dims)}"
)
- self.frame_apply: Dict[int, callable] = dict()
+ self._frame_apply: Dict[int, callable] = dict()
if frame_apply is not None:
if callable(frame_apply):
- self.frame_apply = {0: frame_apply}
+ self._frame_apply = {0: frame_apply}
elif isinstance(frame_apply, dict):
- self.frame_apply: Dict[int, callable] = dict.fromkeys(
+ self._frame_apply: Dict[int, callable] = dict.fromkeys(
list(range(len(self.data)))
)
@@ -510,7 +523,7 @@ def __init__(
if not isinstance(data_ix, int):
raise TypeError("`frame_apply` dict keys must be ")
try:
- self.frame_apply[data_ix] = frame_apply[data_ix]
+ self._frame_apply[data_ix] = frame_apply[data_ix]
except Exception:
raise IndexError(
f"key index {data_ix} out of bounds for `frame_apply`, the bounds are 0 - {len(self.data)}"
@@ -521,14 +534,14 @@ def __init__(
f"you have passed a: <{type(frame_apply)}>"
)
+ # current_index stores {dimension_index: slice_index} for every dimension
+ self._current_index: Dict[str, int] = {sax: 0 for sax in self.slider_dims}
+
self._window_funcs = None
self.window_funcs = window_funcs
self._sliders: Dict[str, Any] = dict()
- # current_index stores {dimension_index: slice_index} for every dimension
- self._current_index: Dict[str, int] = {sax: 0 for sax in self.slider_dims}
-
# get max bound for all data arrays for all dimensions
self._dims_max_bounds: Dict[str, int] = {k: np.inf for k in self.slider_dims}
for _dim in list(self._dims_max_bounds.keys()):
@@ -537,7 +550,7 @@ def __init__(
self._dims_max_bounds[_dim], array.shape[order.index(_dim)]
)
- grid_plot_kwargs_default = {"controllers": "sync"}
+ grid_plot_kwargs_default = {"controller_ids": "sync"}
if grid_plot_kwargs is None:
grid_plot_kwargs = dict()
@@ -575,6 +588,19 @@ def __init__(
self.block_sliders = False
self._image_widget_toolbar = None
+ @property
+ def frame_apply(self) -> Union[dict, None]:
+ return self._frame_apply
+
+ @frame_apply.setter
+ def frame_apply(self, frame_apply: Dict[int, callable]):
+ if frame_apply is None:
+ frame_apply = dict()
+
+ self._frame_apply = frame_apply
+ # force update image graphic
+ self.current_index = self.current_index
+
@property
def window_funcs(self) -> Dict[str, _WindowFunctions]:
"""
@@ -591,6 +617,8 @@ def window_funcs(self) -> Dict[str, _WindowFunctions]:
def window_funcs(self, sa: Union[int, Dict[str, int]]):
if sa is None:
self._window_funcs = None
+ # force frame to update
+ self.current_index = self.current_index
return
# for a single dim
@@ -606,7 +634,7 @@ def window_funcs(self, sa: Union[int, Dict[str, int]]):
dim_str = self.slider_dims[0]
self._window_funcs = dict()
- self._window_funcs[dim_str] = _WindowFunctions(*sa)
+ self._window_funcs[dim_str] = _WindowFunctions(self, *sa)
# for multiple dims
elif isinstance(sa, dict):
@@ -636,7 +664,7 @@ def window_funcs(self, sa: Union[int, Dict[str, int]]):
if sa[k] is None:
self._window_funcs[k] = None
else:
- self._window_funcs[k] = _WindowFunctions(*sa[k])
+ self._window_funcs[k] = _WindowFunctions(self, *sa[k])
else:
raise TypeError(
@@ -644,6 +672,9 @@ def window_funcs(self, sa: Union[int, Dict[str, int]]):
f"You have passed a {type(sa)}. See the docstring."
)
+ # force frame to update
+ self.current_index = self.current_index
+
def _process_indices(
self, array: np.ndarray, slice_indices: Dict[Union[int, str], int]
) -> np.ndarray:
@@ -750,14 +781,14 @@ def _get_window_indices(self, data_ix, dim, indices_dim):
return indices_dim
def _process_frame_apply(self, array, data_ix) -> np.ndarray:
- if callable(self.frame_apply):
- return self.frame_apply(array)
+ if callable(self._frame_apply):
+ return self._frame_apply(array)
- if data_ix not in self.frame_apply.keys():
+ if data_ix not in self._frame_apply.keys():
return array
- elif self.frame_apply[data_ix] is not None:
- return self.frame_apply[data_ix](array)
+ elif self._frame_apply[data_ix] is not None:
+ return self._frame_apply[data_ix](array)
return array
@@ -783,8 +814,14 @@ def reset_vmin_vmax_frame(self):
ImageGraphic instead of the data in the full data array. For example, if a post-processing
function is used, the range of values in the ImageGraphic can be very different from the
range of values in the full data array.
+
+ TODO: We could think of applying the frame_apply funcs to a subsample of the entire array to get a better estimate of vmin vmax?
"""
+
for subplot in self.gridplot:
+ if "histogram_lut" not in subplot.docks["right"]:
+ continue
+
hlut = subplot.docks["right"]["histogram_lut"]
# set the data using the current image graphic data
hlut.set_data(subplot["image_widget_managed"].data())
@@ -854,6 +891,7 @@ def set_data(
frame = self._process_frame_apply(frame, i)
new_graphic = ImageGraphic(data=frame, name="image_widget_managed")
subplot.insert_graphic(graphic=new_graphic)
+ subplot.docks["right"]["histogram_lut"].image_graphic = new_graphic
if new_array.ndim > 2:
# to set max of time slider, txy or tzxy
@@ -876,11 +914,12 @@ def set_data(
def show(self, toolbar: bool = True, sidecar: bool = False, sidecar_kwargs: dict = None):
"""
- Show the widget
+ Show the widget.
Returns
-------
OutputContext
+ ImageWidget just uses the Gridplot output context
"""
if self.gridplot.canvas.__class__.__name__ == "JupyterWgpuCanvas":
self._image_widget_toolbar = IpywidgetImageWidgetToolbar(self)
@@ -888,13 +927,15 @@ def show(self, toolbar: bool = True, sidecar: bool = False, sidecar_kwargs: dict
elif self.gridplot.canvas.__class__.__name__ == "QWgpuCanvas":
self._image_widget_toolbar = QToolbarImageWidget(self)
- return self.gridplot.show(
+ self._output = self.gridplot.show(
toolbar=toolbar,
sidecar=sidecar,
sidecar_kwargs=sidecar_kwargs,
add_widgets=[self._image_widget_toolbar]
)
+ return self._output
+
def close(self):
"""Close Widget"""
self.gridplot.close()
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index d0bc814f2..000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-numpy
-jupyterlab
-jupyter_rfb
-pygfx>=0.1.10
-imageio
\ No newline at end of file
diff --git a/setup.py b/setup.py
index f7195461c..8e8977b57 100644
--- a/setup.py
+++ b/setup.py
@@ -36,7 +36,7 @@
"pytest",
"nbmake",
"scipy",
- "imageio",
+ "imageio[pyav]",
"jupyterlab",
"jupyter-rfb>=0.4.1",
"ipywidgets>=8.0.0,<9",
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy