From 363df5aef2a0b7205f52c68ec122d6597f6579df Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Mon, 13 Nov 2023 18:27:31 -0500 Subject: [PATCH 01/13] try CI with bigmem runner again (#363) bigmem runner works --- .github/workflows/ci.yml | 6 +++--- .github/workflows/screenshots.yml | 2 +- examples/desktop/screenshots/gridplot.png | 4 ++-- examples/desktop/screenshots/image_cmap.png | 4 ++-- examples/desktop/screenshots/image_rgb.png | 4 ++-- examples/desktop/screenshots/image_rgbvminvmax.png | 4 ++-- examples/desktop/screenshots/image_simple.png | 4 ++-- examples/desktop/screenshots/image_vminvmax.png | 4 ++-- examples/desktop/screenshots/line.png | 4 ++-- examples/desktop/screenshots/line_cmap.png | 4 ++-- examples/desktop/screenshots/line_collection.png | 4 ++-- .../desktop/screenshots/line_collection_cmap_values.png | 4 ++-- .../screenshots/line_collection_cmap_values_qualitative.png | 4 ++-- examples/desktop/screenshots/line_collection_colors.png | 4 ++-- examples/desktop/screenshots/line_colorslice.png | 4 ++-- examples/desktop/screenshots/line_dataslice.png | 4 ++-- examples/desktop/screenshots/line_present_scaling.png | 4 ++-- examples/desktop/screenshots/line_stack.png | 4 ++-- examples/desktop/screenshots/scatter.png | 4 ++-- examples/desktop/screenshots/scatter_cmap.png | 4 ++-- examples/desktop/screenshots/scatter_colorslice.png | 4 ++-- examples/desktop/screenshots/scatter_dataslice.png | 4 ++-- examples/desktop/screenshots/scatter_present.png | 4 ++-- examples/desktop/screenshots/scatter_size.png | 4 ++-- examples/notebooks/screenshots/nb-astronaut.png | 4 ++-- examples/notebooks/screenshots/nb-astronaut_RGB.png | 4 ++-- examples/notebooks/screenshots/nb-camera.png | 4 ++-- examples/notebooks/screenshots/nb-lines-3d.png | 4 ++-- .../screenshots/nb-lines-cmap-jet-values-cosine.png | 4 ++-- examples/notebooks/screenshots/nb-lines-cmap-jet-values.png | 4 ++-- examples/notebooks/screenshots/nb-lines-cmap-jet.png | 4 ++-- examples/notebooks/screenshots/nb-lines-cmap-tab-10.png | 4 ++-- .../notebooks/screenshots/nb-lines-cmap-viridis-values.png | 4 ++-- examples/notebooks/screenshots/nb-lines-cmap-viridis.png | 4 ++-- examples/notebooks/screenshots/nb-lines-cmap-white.png | 4 ++-- examples/notebooks/screenshots/nb-lines-colors.png | 4 ++-- examples/notebooks/screenshots/nb-lines-data.png | 4 ++-- examples/notebooks/screenshots/nb-lines-underlay.png | 4 ++-- examples/notebooks/screenshots/nb-lines.png | 4 ++-- 39 files changed, 78 insertions(+), 78 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c15e3865..08a36a971 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 @@ -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..39797b95b 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 diff --git a/examples/desktop/screenshots/gridplot.png b/examples/desktop/screenshots/gridplot.png index f2cbb1e7a..eafded3b1 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:a83704df89be660a6797e27ae4031ab48eb21f061a94cfdeb007a022b745de06 +size 350327 diff --git a/examples/desktop/screenshots/image_cmap.png b/examples/desktop/screenshots/image_cmap.png index cf3ae8ac0..f2a628a8b 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:8cc6aa770845f05bdc8914d3c983504f7a75b316a24e8e2b182c05145187b3e2 +size 274798 diff --git a/examples/desktop/screenshots/image_rgb.png b/examples/desktop/screenshots/image_rgb.png index 5681017c8..90f1da3c2 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:3372487a5ae0fd47095ffbfc90915b94ff1a54c463ae887474f6eadd04801d6b +size 319514 diff --git a/examples/desktop/screenshots/image_rgbvminvmax.png b/examples/desktop/screenshots/image_rgbvminvmax.png index aea5fdf85..a89c4de3e 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:026ea433786e50aa3d9e0fa8eb1d921617e52aca97eb6ffd5c8b297f1cd69c79 +size 44787 diff --git a/examples/desktop/screenshots/image_simple.png b/examples/desktop/screenshots/image_simple.png index 5ab073433..010101d59 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:64803f58bd07e87d171e66eb9437d4fcc2ec1781e4da150a7229f6deef0835ad +size 272599 diff --git a/examples/desktop/screenshots/image_vminvmax.png b/examples/desktop/screenshots/image_vminvmax.png index aea5fdf85..a89c4de3e 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:026ea433786e50aa3d9e0fa8eb1d921617e52aca97eb6ffd5c8b297f1cd69c79 +size 44787 diff --git a/examples/desktop/screenshots/line.png b/examples/desktop/screenshots/line.png index a38008ab9..0160a3213 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:164e5c36d57707da3ab928fe79312b4362de083c8422fc126ebc6cbc895eb022 +size 49783 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..ebacf9170 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:3f708da0a80ec8776da28052835e19132bee8e1a1e301021bf4bc5f44e6a8825 +size 57105 diff --git a/examples/desktop/screenshots/line_dataslice.png b/examples/desktop/screenshots/line_dataslice.png index 20c777212..55fd20a91 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:91a3995675530ed2132149e2c2f1dad6731b5d9ec7b503d78da133db1e06cae0 +size 75481 diff --git a/examples/desktop/screenshots/line_present_scaling.png b/examples/desktop/screenshots/line_present_scaling.png index c4a41ac2e..bcb84b62b 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:b7b8d50cbbd9b1dafbf9a6559ef974c53e14e2a8106fa0c5c3c065fc532c76e5 +size 43413 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..48e22fe53 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:8d806d252ee03ade60cffcc651ebe041560bcc095f5aaeacf43f3ffb4d29f660 +size 25231 diff --git a/examples/desktop/screenshots/scatter_cmap.png b/examples/desktop/screenshots/scatter_cmap.png index 10477e81b..06b94d9ed 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:e1c0c2b899fdb0e5456ec7305ba20a5fc04b715f88c834715fcb867d456d58b3 +size 59401 diff --git a/examples/desktop/screenshots/scatter_colorslice.png b/examples/desktop/screenshots/scatter_colorslice.png index cd5a1f00d..f9edc4d6a 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:3d271bf913c196559ae0f5e323326dc9f68b015ce0d2078d775371ff57bef309 +size 23746 diff --git a/examples/desktop/screenshots/scatter_dataslice.png b/examples/desktop/screenshots/scatter_dataslice.png index 8ed7ad590..c444b2604 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:ef00ef6e6babf9fbfd18b7c1b91cc80c6c1dd0253d7f5fbb2a7b9a900dad4e41 +size 25996 diff --git a/examples/desktop/screenshots/scatter_present.png b/examples/desktop/screenshots/scatter_present.png index 335191d91..3c19441b6 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:cf630459458da82853919717908d433ab1fe846f2158a30b7ef7ddbd53ae418d +size 24617 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/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-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..d9164c635 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:fd21151b5af0065b25e20b7e382d310afebb3ee36ab12acadc6188b6adf4b128 +size 55961 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 From 37687592fe3788caa387f052f49c793372e2be45 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Wed, 15 Nov 2023 23:05:07 -0500 Subject: [PATCH 02/13] set canvas default 60fps (#370) --- fastplotlib/layouts/_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastplotlib/layouts/_utils.py b/fastplotlib/layouts/_utils.py index dd6fbeb50..e8201d073 100644 --- a/fastplotlib/layouts/_utils.py +++ b/fastplotlib/layouts/_utils.py @@ -66,7 +66,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 +76,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( From 7350b81e66c0cacd4246d12812d0d6943d31c498 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Wed, 15 Nov 2023 23:19:00 -0500 Subject: [PATCH 03/13] `Plot.auto_scale()` shouldn't change the camera aspect unless desired (#364) * now auto_scale() by default does not change camera aspect * center_scene() and maintain_aspect() take only kwargs * update screenshot images after auto_scale() fix --- examples/desktop/screenshots/gridplot.png | 4 ++-- .../screenshots/gridplot_non_square.png | 4 ++-- examples/desktop/screenshots/heatmap.png | 4 ++-- examples/desktop/screenshots/heatmap_cmap.png | 4 ++-- examples/desktop/screenshots/heatmap_data.png | 4 ++-- .../desktop/screenshots/heatmap_vmin_vmax.png | 4 ++-- examples/desktop/screenshots/image_cmap.png | 4 ++-- examples/desktop/screenshots/image_rgb.png | 4 ++-- .../desktop/screenshots/image_rgbvminvmax.png | 4 ++-- examples/desktop/screenshots/image_simple.png | 4 ++-- .../desktop/screenshots/image_vminvmax.png | 4 ++-- examples/desktop/screenshots/line.png | 4 ++-- .../desktop/screenshots/line_colorslice.png | 4 ++-- .../desktop/screenshots/line_dataslice.png | 4 ++-- .../screenshots/line_present_scaling.png | 4 ++-- examples/desktop/screenshots/scatter.png | 2 +- examples/desktop/screenshots/scatter_cmap.png | 4 ++-- .../screenshots/scatter_colorslice.png | 4 ++-- .../desktop/screenshots/scatter_dataslice.png | 4 ++-- .../desktop/screenshots/scatter_present.png | 4 ++-- .../screenshots/nb-lines-underlay.png | 4 ++-- fastplotlib/layouts/_plot_area.py | 20 ++++++++++++------- 22 files changed, 54 insertions(+), 48 deletions(-) diff --git a/examples/desktop/screenshots/gridplot.png b/examples/desktop/screenshots/gridplot.png index eafded3b1..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:a83704df89be660a6797e27ae4031ab48eb21f061a94cfdeb007a022b745de06 -size 350327 +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 f2a628a8b..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:8cc6aa770845f05bdc8914d3c983504f7a75b316a24e8e2b182c05145187b3e2 -size 274798 +oid sha256:e1d78cc0681079a5c43d9fdb4142f5fee75d477d9f9a1469fca8bc8933c244fc +size 216210 diff --git a/examples/desktop/screenshots/image_rgb.png b/examples/desktop/screenshots/image_rgb.png index 90f1da3c2..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:3372487a5ae0fd47095ffbfc90915b94ff1a54c463ae887474f6eadd04801d6b -size 319514 +oid sha256:820a73b9b2e5bbaed84fb11438e2c5672b76c8b57a33823f4840a71be03d7dd1 +size 251438 diff --git a/examples/desktop/screenshots/image_rgbvminvmax.png b/examples/desktop/screenshots/image_rgbvminvmax.png index a89c4de3e..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:026ea433786e50aa3d9e0fa8eb1d921617e52aca97eb6ffd5c8b297f1cd69c79 -size 44787 +oid sha256:5f2f562573f8104342ae01b5852f71c960341bdd70ae0bc7967df663166edbd3 +size 39604 diff --git a/examples/desktop/screenshots/image_simple.png b/examples/desktop/screenshots/image_simple.png index 010101d59..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:64803f58bd07e87d171e66eb9437d4fcc2ec1781e4da150a7229f6deef0835ad -size 272599 +oid sha256:a4ed42d042d8bb7e35f31b5ad0a3e3a495cf9c3164516eb457d8b41d7fae6bab +size 213075 diff --git a/examples/desktop/screenshots/image_vminvmax.png b/examples/desktop/screenshots/image_vminvmax.png index a89c4de3e..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:026ea433786e50aa3d9e0fa8eb1d921617e52aca97eb6ffd5c8b297f1cd69c79 -size 44787 +oid sha256:5f2f562573f8104342ae01b5852f71c960341bdd70ae0bc7967df663166edbd3 +size 39604 diff --git a/examples/desktop/screenshots/line.png b/examples/desktop/screenshots/line.png index 0160a3213..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:164e5c36d57707da3ab928fe79312b4362de083c8422fc126ebc6cbc895eb022 -size 49783 +oid sha256:018f4a36c60b3de2f1406aa2823b751de5fae2c2340f9d49368d007ba7379637 +size 44422 diff --git a/examples/desktop/screenshots/line_colorslice.png b/examples/desktop/screenshots/line_colorslice.png index ebacf9170..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:3f708da0a80ec8776da28052835e19132bee8e1a1e301021bf4bc5f44e6a8825 -size 57105 +oid sha256:5bd80cee80f491da6ab64c868a3c70254a68072e0bc0caad80c7999cadcb2df9 +size 50497 diff --git a/examples/desktop/screenshots/line_dataslice.png b/examples/desktop/screenshots/line_dataslice.png index 55fd20a91..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:91a3995675530ed2132149e2c2f1dad6731b5d9ec7b503d78da133db1e06cae0 -size 75481 +oid sha256:823651905a775b5cbcc2ce0f79d25d69b29f17b4c060c244d80ae87019f05d5b +size 69332 diff --git a/examples/desktop/screenshots/line_present_scaling.png b/examples/desktop/screenshots/line_present_scaling.png index bcb84b62b..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:b7b8d50cbbd9b1dafbf9a6559ef974c53e14e2a8106fa0c5c3c065fc532c76e5 -size 43413 +oid sha256:3d18669d5e75cee3326d0380ae5dd26cab71ea97725ff99bc5228d2555d51454 +size 30373 diff --git a/examples/desktop/screenshots/scatter.png b/examples/desktop/screenshots/scatter.png index 48e22fe53..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:8d806d252ee03ade60cffcc651ebe041560bcc095f5aaeacf43f3ffb4d29f660 +oid sha256:bd38399b77e09d915c5bb1e7ee022f936ae90682f598357bc774a95c372dc78f size 25231 diff --git a/examples/desktop/screenshots/scatter_cmap.png b/examples/desktop/screenshots/scatter_cmap.png index 06b94d9ed..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:e1c0c2b899fdb0e5456ec7305ba20a5fc04b715f88c834715fcb867d456d58b3 -size 59401 +oid sha256:e712693b403166909dcaa65256131eacba0a15892cd144ad97fdecb6b9835e93 +size 57273 diff --git a/examples/desktop/screenshots/scatter_colorslice.png b/examples/desktop/screenshots/scatter_colorslice.png index f9edc4d6a..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:3d271bf913c196559ae0f5e323326dc9f68b015ce0d2078d775371ff57bef309 -size 23746 +oid sha256:c620cad9976f390e44a5b037f3ff61fb80e6487e17f4be8118be5df55f276a35 +size 23664 diff --git a/examples/desktop/screenshots/scatter_dataslice.png b/examples/desktop/screenshots/scatter_dataslice.png index c444b2604..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:ef00ef6e6babf9fbfd18b7c1b91cc80c6c1dd0253d7f5fbb2a7b9a900dad4e41 -size 25996 +oid sha256:69d2f0999b0bb334e48320702095fc76444f4d89d43a51ac6c5c8f49e1df96ac +size 25999 diff --git a/examples/desktop/screenshots/scatter_present.png b/examples/desktop/screenshots/scatter_present.png index 3c19441b6..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:cf630459458da82853919717908d433ab1fe846f2158a30b7ef7ddbd53ae418d -size 24617 +oid sha256:e45c1a936771e569e562ed3496421e498e725325093e84243ab494c0718ead3a +size 23639 diff --git a/examples/notebooks/screenshots/nb-lines-underlay.png b/examples/notebooks/screenshots/nb-lines-underlay.png index d9164c635..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:fd21151b5af0065b25e20b7e382d310afebb3ee36ab12acadc6188b6adf4b128 -size 55961 +oid sha256:70800d1739bb5ba7d5d9d2399335ebc1ce8a0874042ed4b6256b6d041014eb18 +size 55884 diff --git a/fastplotlib/layouts/_plot_area.py b/fastplotlib/layouts/_plot_area.py index 7590bad10..dec5d891e 100644 --- a/fastplotlib/layouts/_plot_area.py +++ b/fastplotlib/layouts/_plot_area.py @@ -459,7 +459,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 +481,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 +508,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: From b1242d4d31731560936a6d0adbac39437187d1dd Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Thu, 16 Nov 2023 01:54:52 -0500 Subject: [PATCH 04/13] `ImageWidget` notebook tests (#371) * add .npy to gitattributes * add zfish data file * update imagewidget user demo, add imagewidget test nb, imagewidget auto-updates w.r.t. window_funcs and frame_apply * use scipy instead of skimage for gaussian filter example * add ffmpeg to ci * add imageio[pyav] * allow_pickle=True for zfish npy load * add git lfs fetch to screenshots ci, remove allow_pickle * add imagewidget ground-truth screenshots --- .gitattributes | 2 + .github/workflows/ci.yml | 2 +- .github/workflows/screenshots.yml | 6 +- examples/notebooks/image_widget.ipynb | 199 +++++--- examples/notebooks/image_widget_test.ipynb | 468 ++++++++++++++++++ .../nb-image-widget-movie-set_data.png | 3 + .../nb-image-widget-movie-single-0-reset.png | 3 + .../nb-image-widget-movie-single-0.png | 3 + .../nb-image-widget-movie-single-279.png | 3 + ...e-widget-movie-single-50-window-max-33.png | 3 + ...-widget-movie-single-50-window-mean-13.png | 3 + ...-widget-movie-single-50-window-mean-33.png | 3 + ...ge-widget-movie-single-50-window-reset.png | 3 + .../nb-image-widget-movie-single-50.png | 3 + .../nb-image-widget-single-gnuplot2.png | 3 + .../screenshots/nb-image-widget-single.png | 3 + ...et-zfish-frame-50-frame-apply-gaussian.png | 3 + ...idget-zfish-frame-50-frame-apply-reset.png | 3 + ...ge-widget-zfish-frame-50-max-window-13.png | 3 + ...e-widget-zfish-frame-50-mean-window-13.png | 3 + ...ge-widget-zfish-frame-50-mean-window-5.png | 3 + .../nb-image-widget-zfish-frame-50.png | 3 + .../nb-image-widget-zfish-frame-99.png | 3 + ...ish-grid-frame-50-frame-apply-gaussian.png | 3 + ...-zfish-grid-frame-50-frame-apply-reset.png | 3 + ...dget-zfish-grid-frame-50-max-window-13.png | 3 + ...get-zfish-grid-frame-50-mean-window-13.png | 3 + ...dget-zfish-grid-frame-50-mean-window-5.png | 3 + .../nb-image-widget-zfish-grid-frame-50.png | 3 + .../nb-image-widget-zfish-grid-frame-99.png | 3 + ...e-widget-zfish-grid-init-mean-window-5.png | 3 + ...fish-grid-set_data-reset-indices-false.png | 3 + ...zfish-grid-set_data-reset-indices-true.png | 3 + ...-image-widget-zfish-init-mean-window-5.png | 3 + examples/notebooks/zfish_test.npy | 3 + fastplotlib/widgets/image.py | 70 ++- setup.py | 2 +- 37 files changed, 761 insertions(+), 78 deletions(-) create mode 100644 examples/notebooks/image_widget_test.ipynb create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-set_data.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-0-reset.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-0.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-279.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-max-33.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-13.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-mean-33.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-50-window-reset.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-movie-single-50.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-single.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-gaussian.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-frame-apply-reset.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-max-window-13.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-13.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-frame-50-mean-window-5.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-gaussian.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-frame-apply-reset.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-max-window-13.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-13.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50-mean-window-5.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-99.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-init-mean-window-5.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-false.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-grid-set_data-reset-indices-true.png create mode 100644 examples/notebooks/screenshots/nb-image-widget-zfish-init-mean-window-5.png create mode 100644 examples/notebooks/zfish_test.npy 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 08a36a971..fddfae5f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 diff --git a/.github/workflows/screenshots.yml b/.github/workflows/screenshots.yml index 39797b95b..d3cdb919b 100644 --- a/.github/workflows/screenshots.yml +++ b/.github/workflows/screenshots.yml @@ -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/examples/notebooks/image_widget.ipynb b/examples/notebooks/image_widget.ipynb index d8f91c1be..296126f5e 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,8 @@ }, "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" ] }, { @@ -214,7 +240,7 @@ "id": "aca22179-1b1f-4c51-97bf-ce2d7044e451", "metadata": {}, "source": [ - "# Gridplot of txy data" + "# Gridplot of tzxy data" ] }, { @@ -226,8 +252,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,12 +286,10 @@ }, "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", ")" ] @@ -254,7 +299,7 @@ "id": "0721dc40-677e-431d-94c6-da59606199cb", "metadata": {}, "source": [ - "### pan-zoom controllers are all synced in a `ImageWidget`" + "pan-zoom controllers are all synced across subplots in a `ImageWidget`" ] }, { @@ -266,7 +311,7 @@ }, "outputs": [], "source": [ - "iw3.show()" + "iw_zfish.show(sidecar=True)" ] }, { @@ -274,7 +319,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 +331,7 @@ }, "outputs": [], "source": [ - "iw3.gridplot[\"two\"]" + "iw_zfish.gridplot[\"plane-2\"]" ] }, { @@ -294,7 +339,7 @@ "id": "dc727d1a-681e-4cbf-bfb2-898ceb31cbe0", "metadata": {}, "source": [ - "### change window functions just like before" + "change window functions" ] }, { @@ -306,70 +351,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": [ - "iw4.show()" + "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": [ + "# 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": { @@ -388,7 +473,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.3" + "version": "3.11.2" } }, "nbformat": 4, diff --git a/examples/notebooks/image_widget_test.ipynb b/examples/notebooks/image_widget_test.ipynb new file mode 100644 index 000000000..6602dfce9 --- /dev/null +++ b/examples/notebooks/image_widget_test.ipynb @@ -0,0 +1,468 @@ +{ + "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": [] + } + ], + "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/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..33798861e --- /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:df2f6e73fdb0946d915f40df1e27f2ae89ba6c6e5d0dadb84406fe8b753735ab +size 34974 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/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/widgets/image.py b/fastplotlib/widgets/image.py index da256207f..522b0a962 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()): @@ -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 @@ -876,11 +907,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 +920,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/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", From 17f09c6a0ac12b49598187fc16d4a90047ccfbdf Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Thu, 16 Nov 2023 02:05:09 -0500 Subject: [PATCH 05/13] histogram calculation fix, now n_edges always == hist (#372) --- fastplotlib/widgets/histogram_lut.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From 568163f7e7bcb9c470384d8fb2e422bdc20fab06 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Thu, 16 Nov 2023 02:35:47 -0500 Subject: [PATCH 06/13] forget notebook_finished() call (#373) --- examples/notebooks/image_widget_test.ipynb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/notebooks/image_widget_test.ipynb b/examples/notebooks/image_widget_test.ipynb index 6602dfce9..90747757c 100644 --- a/examples/notebooks/image_widget_test.ipynb +++ b/examples/notebooks/image_widget_test.ipynb @@ -441,7 +441,9 @@ "id": "870627ef-09d8-44e4-8952-aedb702d1526", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "notebook_finished()" + ] } ], "metadata": { From e53067cc07ef8bac4c3eb5bc0cc0e2aa382a6be0 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Fri, 17 Nov 2023 00:34:09 -0500 Subject: [PATCH 07/13] Delete requirements.txt --- requirements.txt | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 requirements.txt 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 From f6d2e2b02cd3bb2b05fbb361a5d08c3fb61510f8 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Tue, 21 Nov 2023 19:59:42 -0500 Subject: [PATCH 08/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f9ccf547..e0028971f 100644 --- a/README.md +++ b/README.md @@ -167,4 +167,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! From dece084fa76a28eba6c69e069badc23fdc0cb2c9 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Wed, 22 Nov 2023 23:24:45 -0500 Subject: [PATCH 09/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e0028971f..8604d6aeb 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,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 From c7622818e3ff6eebc8ccde562616dfe1696756c1 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Wed, 22 Nov 2023 23:31:37 -0500 Subject: [PATCH 10/13] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8604d6aeb..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) From 5f47fd4cff7a40f77ad7cbdad6275cce67d98739 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Sun, 26 Nov 2023 06:25:59 -0500 Subject: [PATCH 11/13] fix bug, skip if hlut not in iw dock (#378) --- fastplotlib/widgets/image.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index 522b0a962..b25785ecf 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -814,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()) From 21762a5a1d6d7c3c33770e5819f955c99e807823 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Wed, 29 Nov 2023 21:30:21 -0500 Subject: [PATCH 12/13] cameras and controllers refactor (#382) * reorganize camera and controller initialization, allow setting them, WIP * controllers named sync done, not tested yet * new controllers work, ids also works, changing controllers works * bugfix * update nb examples * update nbs * controller changes for imagewidget * fix type annotation * update example * update example * update quickstart nb * update screenshot * use perspective camera for everything * typo Co-authored-by: Caitlin Lewis <69729525+clewis7@users.noreply.github.com> * typo Co-authored-by: Caitlin Lewis <69729525+clewis7@users.noreply.github.com> * more detailed exception * better names --------- Co-authored-by: Caitlin Lewis <69729525+clewis7@users.noreply.github.com> --- docs/source/quickstart.ipynb | 46 +--- .../desktop/gridplot/gridplot_non_square.py | 2 +- examples/desktop/scatter/scatter_size.py | 14 +- examples/notebooks/gridplot.ipynb | 150 +++--------- examples/notebooks/gridplot_simple.ipynb | 142 +++--------- examples/notebooks/image_widget.ipynb | 14 +- examples/notebooks/lineplot.ipynb | 62 +---- examples/notebooks/scatter.ipynb | 14 +- .../notebooks/scatter_sizes_animation.ipynb | 52 +++-- examples/notebooks/scatter_sizes_grid.ipynb | 26 +-- .../nb-image-widget-movie-set_data.png | 4 +- examples/notebooks/simple.ipynb | 44 +++- fastplotlib/layouts/_defaults.py | 43 ---- fastplotlib/layouts/_gridplot.py | 216 ++++++++++++------ fastplotlib/layouts/_plot.py | 14 +- fastplotlib/layouts/_plot_area.py | 112 ++++++--- fastplotlib/layouts/_subplot.py | 65 +++--- fastplotlib/layouts/_utils.py | 56 +++++ fastplotlib/widgets/image.py | 3 +- 19 files changed, 510 insertions(+), 569 deletions(-) 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/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 296126f5e..56d5c8a81 100644 --- a/examples/notebooks/image_widget.ipynb +++ b/examples/notebooks/image_widget.ipynb @@ -235,6 +235,16 @@ "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()" + ] + }, { "cell_type": "markdown", "id": "aca22179-1b1f-4c51-97bf-ce2d7044e451", @@ -296,7 +306,7 @@ }, { "cell_type": "markdown", - "id": "0721dc40-677e-431d-94c6-da59606199cb", + "id": "037d899e-9e7c-4d58-a021-5f5b71e1db90", "metadata": {}, "source": [ "pan-zoom controllers are all synced across subplots in a `ImageWidget`" @@ -473,7 +483,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.3" } }, "nbformat": 4, 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-image-widget-movie-set_data.png b/examples/notebooks/screenshots/nb-image-widget-movie-set_data.png index 33798861e..61c3aeb8c 100644 --- a/examples/notebooks/screenshots/nb-image-widget-movie-set_data.png +++ b/examples/notebooks/screenshots/nb-image-widget-movie-set_data.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df2f6e73fdb0946d915f40df1e27f2ae89ba6c6e5d0dadb84406fe8b753735ab -size 34974 +oid sha256:60318615e4850d37a4ffae16ca1e3bbf2985ddafd0dd65ba6fae997e1d123d67 +size 31251 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/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 dec5d891e..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.""" @@ -663,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 e8201d073..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 @@ -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/image.py b/fastplotlib/widgets/image.py index b25785ecf..a3f6335c9 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -550,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() @@ -891,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 From 2873a677462551f47881e4c6dad637165f5230f6 Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Thu, 30 Nov 2023 13:52:49 -0500 Subject: [PATCH 13/13] Update VERSION --- fastplotlib/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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