diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f92bafb8..53e88bdf8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,15 +46,13 @@ jobs: make html SPHINXOPTS="-W --keep-going" test-build-full: - name: Test examples, env with notebook and glfw + name: Test Linux, notebook + glfw runs-on: bigmem if: ${{ !github.event.pull_request.draft }} strategy: fail-fast: false matrix: include: - - name: Test py39 - pyversion: '3.9' - name: Test py310 pyversion: '3.10' - name: Test py311 @@ -103,15 +101,13 @@ jobs: examples/notebooks/diffs test-build-desktop: - name: Test examples, env with only glfw + name: Test Linux, only glfw runs-on: bigmem if: ${{ !github.event.pull_request.draft }} strategy: fail-fast: false matrix: include: - - name: Test py39 - pyversion: '3.9' - name: Test py310 pyversion: '3.10' - name: Test py311 @@ -156,3 +152,87 @@ jobs: name: screenshot-diffs path: | examples/desktop/diffs + +# test-build-full-mac: +# name: Test Mac, notebook + glfw +# runs-on: macos-14 +# if: ${{ !github.event.pull_request.draft }} +# strategy: +# fail-fast: false +# matrix: +# include: +# - name: Test py310 +# pyversion: '3.10' +# - name: Test py311 +# pyversion: '3.11' +# - name: Test py312 +# pyversion: '3.12' +# steps: +# - uses: actions/checkout@v3 +# with: +# lfs: true +# - name: Set up Python +# uses: actions/setup-python@v3 +# with: +# python-version: ${{ matrix.pyversion }} +# - name: Install dev dependencies +# run: | +# python -m pip install --upgrade pip setuptools +# # remove pygfx from install_requires, we install using pygfx@main +# pip install -e ".["tests"]" +# pip install git+https://github.com/pygfx/pygfx.git@main +# - name: Show wgpu backend +# run: +# python -c "from examples.tests.testutils import wgpu_backend; print(wgpu_backend)" +# - name: Test examples +# run: | +# pytest -v examples +# pytest --nbmake examples/notebooks/ +# - uses: actions/upload-artifact@v3 +# if: ${{ failure() }} +# with: +# name: screenshot-diffs +# path: | +# examples/desktop/diffs +# examples/notebooks/diffs +# +# test-build-glfw-mac: +# name: Test Mac, glfw +# runs-on: macos-14 +# if: ${{ !github.event.pull_request.draft }} +# strategy: +# fail-fast: false +# matrix: +# include: +# - name: Test py310 +# pyversion: '3.10' +# - name: Test py311 +# pyversion: '3.11' +# - name: Test py312 +# pyversion: '3.12' +# steps: +# - uses: actions/checkout@v3 +# with: +# lfs: true +# - name: Set up Python +# uses: actions/setup-python@v3 +# with: +# python-version: ${{ matrix.pyversion }} +# - name: Install dev dependencies +# run: | +# python -m pip install --upgrade pip setuptools +# # remove pygfx from install_requires, we install using pygfx@main +# pip install -e ".["tests-desktop"]" +# pip install git+https://github.com/pygfx/pygfx.git@main +# - name: Show wgpu backend +# run: +# python -c "from examples.tests.testutils import wgpu_backend; print(wgpu_backend)" +# - name: Test examples +# run: | +# pytest -v examples +# - uses: actions/upload-artifact@v3 +# if: ${{ failure() }} +# with: +# name: screenshot-diffs +# path: | +# examples/desktop/diffs diff --git a/.github/workflows/screenshots.yml b/.github/workflows/screenshots.yml index d3cdb919b..baad8b655 100644 --- a/.github/workflows/screenshots.yml +++ b/.github/workflows/screenshots.yml @@ -48,7 +48,7 @@ jobs: run: | # regenerate screenshots REGENERATE_SCREENSHOTS=1 pytest -v examples - REGENERATE_SCREENSHOTS=1 pytest --nbmake examples/notebooks/ + FASTPLOTLIB_NB_TESTS=1 REGENERATE_SCREENSHOTS=1 pytest --nbmake examples/notebooks/ - uses: actions/upload-artifact@v3 if: always() with: diff --git a/examples/desktop/screenshots/gridplot.png b/examples/desktop/screenshots/gridplot.png index bc35ccf8c..ebf2d3a97 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:e416fc968edd3788513e369f4d265b0abd7216a7ef19ec8b84659c30ca7c8ca1 -size 307384 +oid sha256:f972f67b8830657ab14899f749fb385a080280304377d8868e6cd39c766a0afd +size 267084 diff --git a/examples/desktop/screenshots/gridplot_non_square.png b/examples/desktop/screenshots/gridplot_non_square.png index 82b2b0eb4..bc642b729 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:ab5598b67b80efce0d2559e400e77098e734c91608a3f49b691ddaa030d47edb -size 203434 +oid sha256:352bf94c68444a330b000d7b6b3ec51b5b694ff3a0ce810299b325315923d9af +size 175938 diff --git a/examples/desktop/screenshots/heatmap.png b/examples/desktop/screenshots/heatmap.png index a0655cf3a..a8c8b73fe 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:6872c3cc3e35ec918b054fb2d76525bbd3d82d8b49916aca1046aa1be65ff923 -size 111825 +oid sha256:5620e4dcb964dbf3318ac77e566af395a35b9762e0687dec2e1a2864eb291fd3 +size 102994 diff --git a/examples/desktop/screenshots/heatmap_cmap.png b/examples/desktop/screenshots/heatmap_cmap.png index 2eb769c14..cee81dd30 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:f2eba96c2bfb1d07365810a69e99c79b068741f5dcf74fc745c13d5ff21f16f2 -size 106671 +oid sha256:8863461569f5b89d1443e3051a5512f3987487fcb9e057215d2f030a180fa09f +size 97996 diff --git a/examples/desktop/screenshots/heatmap_data.png b/examples/desktop/screenshots/heatmap_data.png index 50a8ae79e..316a73753 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:f0576063658e05e19b7723b4c88dc4d55a8178b090b4a88e33251fc92408b4a1 -size 18051 +oid sha256:a975179e82893dbb04e4674310761e7b02bb62ae6abb1b89397720bddf96ae5f +size 19084 diff --git a/examples/desktop/screenshots/heatmap_vmin_vmax.png b/examples/desktop/screenshots/heatmap_vmin_vmax.png index f10382e87..357683d82 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:639d50f2f5fb07dba461e7a38de3886092f8754277eadbb5e305e32023289abd -size 124403 +oid sha256:9592f3724016db1b7431bc100b16bec175e197c111e7b442dc2255d51da3f5e8 +size 114957 diff --git a/examples/desktop/screenshots/image_cmap.png b/examples/desktop/screenshots/image_cmap.png index bed07a41a..bbf51ab18 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:e1d78cc0681079a5c43d9fdb4142f5fee75d477d9f9a1469fca8bc8933c244fc -size 216210 +oid sha256:555fd969606d0cb231ac152724f7c9717a2220ce22db663c5e7d5793f828ed34 +size 189654 diff --git a/examples/desktop/screenshots/image_rgb.png b/examples/desktop/screenshots/image_rgb.png index a21c0658b..9a5082b12 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:820a73b9b2e5bbaed84fb11438e2c5672b76c8b57a33823f4840a71be03d7dd1 -size 251438 +oid sha256:95f3cae6caf8d64d1a6b4799df52dc61cc05bd6b6ea465edbec06a9678f32435 +size 218089 diff --git a/examples/desktop/screenshots/image_rgbvminvmax.png b/examples/desktop/screenshots/image_rgbvminvmax.png index 88acfadc5..00bbdc0c5 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:5f2f562573f8104342ae01b5852f71c960341bdd70ae0bc7967df663166edbd3 -size 39604 +oid sha256:4fc06b8cdd72040cf2ffc44cde80d5ae21ca392daac25d79fe175b5865b13552 +size 34894 diff --git a/examples/desktop/screenshots/image_simple.png b/examples/desktop/screenshots/image_simple.png index 098d5a055..94fcd3061 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:a4ed42d042d8bb7e35f31b5ad0a3e3a495cf9c3164516eb457d8b41d7fae6bab -size 213075 +oid sha256:3dcfb5d48d0e4db920c33ee725e2c66f3c8e04a66e03d283a6481f42a4121a16 +size 190178 diff --git a/examples/desktop/screenshots/image_vminvmax.png b/examples/desktop/screenshots/image_vminvmax.png index 88acfadc5..00bbdc0c5 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:5f2f562573f8104342ae01b5852f71c960341bdd70ae0bc7967df663166edbd3 -size 39604 +oid sha256:4fc06b8cdd72040cf2ffc44cde80d5ae21ca392daac25d79fe175b5865b13552 +size 34894 diff --git a/examples/desktop/screenshots/line.png b/examples/desktop/screenshots/line.png index 8e3e6ae64..74cbae39a 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:81038ebca5d41f22f5dde3fd152d94760ef51cc055ff248be18298bc7537b569 -size 44312 +oid sha256:c8b4f4a08d1791b80d226c8c3099e37d33d8cdd7a400e4f85fb7072ee2aa3c2e +size 29121 diff --git a/examples/desktop/screenshots/line_cmap.png b/examples/desktop/screenshots/line_cmap.png index b96c9a1dd..9cd93f05d 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:e7a9cf65bbd19290ed96e418930e896fd0ec463dc2c6797f8b407d56e9e4444d -size 43730 +oid sha256:d60b4ff117298f973be892773dbfc620ac855c35ca7dea42437e20bf7fcef804 +size 31050 diff --git a/examples/desktop/screenshots/line_collection.png b/examples/desktop/screenshots/line_collection.png index 89d613c2c..bcfe85309 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:09e8c2be9815edf5c29a98dc61758fac3aeb2603c8547aa8c3c05b01538886e3 -size 147244 +oid sha256:7ca99b8d74fdf7f87b0f2fc5637c59c9090b91bef868e85ddd75dbcb1264f699 +size 95146 diff --git a/examples/desktop/screenshots/line_collection_cmap_values.png b/examples/desktop/screenshots/line_collection_cmap_values.png index 38d9adc6e..b7fcdbcae 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:98d7468dc1701d3523c779a0e857cf185201766b751731e1db44e3c2bc753335 -size 93839 +oid sha256:68090603856eb5b961092cf2ad2d89a1e9cfd7e31f6d089b3abad101874f65d4 +size 61032 diff --git a/examples/desktop/screenshots/line_collection_cmap_values_qualitative.png b/examples/desktop/screenshots/line_collection_cmap_values_qualitative.png index 4f14e49b9..9f89a24cc 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:31d79a2aeb2e43b569a9045edd21fb59e7bddf2b5cc18133f4b346e0d6be7fd1 -size 95696 +oid sha256:9cff99e5f9faf319909571778631453c043237f5c94eece6680b028a5d7a5ac2 +size 64149 diff --git a/examples/desktop/screenshots/line_collection_colors.png b/examples/desktop/screenshots/line_collection_colors.png index c71c623c6..7bb4152fd 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:381fc320bda54f5aa235b4cd0183ff511e3a0484c00ab37f76c89df959d48626 -size 82806 +oid sha256:a4aa17a65806300da65f4bbbfccb970d6a7207c4ca4d48b25615f627630fb484 +size 51174 diff --git a/examples/desktop/screenshots/line_colorslice.png b/examples/desktop/screenshots/line_colorslice.png index 7775c1918..3d04c473f 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:3ade0416355a05de01e8f4a55485aacc40bd4c3d57a1a9fcff43317e13a43856 -size 50560 +oid sha256:aa941eaf5b940b4eebab89ed836cbd092e16b4758abafa3722c296db65c0c4b5 +size 33233 diff --git a/examples/desktop/screenshots/line_dataslice.png b/examples/desktop/screenshots/line_dataslice.png index 2907dd64a..0863751bf 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:8fc4265c0ac6b4cee0476acbc5362968f60a965a387c7a0a3b66e89e522eb21c -size 69917 +oid sha256:78ccd51d1891fb6a345cb2885a341f276d8ad7a6fa506deda6cae6ef14c64094 +size 45843 diff --git a/examples/desktop/screenshots/line_present_scaling.png b/examples/desktop/screenshots/line_present_scaling.png index b4b883855..ba7142106 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:f37f2a227136af0cfc112bb1e5c9ba01fb362f33bad0971f5253adb61e89785e -size 30264 +oid sha256:06f7dd45eb495fecfcf46478c6430a658640ceb2855c4797bc184cf4134571e3 +size 20180 diff --git a/examples/desktop/screenshots/line_stack.png b/examples/desktop/screenshots/line_stack.png index 47e59ba8c..c13f05f04 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:0081d587956056934c4feb0c0f695f69ea19a253243f1af1dc7de80c6406a642 -size 365226 +oid sha256:5480aefe6e723863b919a4eeb4755310fe7036b27beb8e2e2402e04943ee8c1e +size 201102 diff --git a/examples/desktop/screenshots/scatter.png b/examples/desktop/screenshots/scatter.png index d01d36707..94fb858e1 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:8d840f02d1c4be5ea11adfc224481a5b8b306cbc904e099af4d3fdd5ab7f383f -size 26683 +oid sha256:4fc16a1ba74a8eca99a2fc7937f8896ca93207b99e231bc4f53845b0d2bdaed7 +size 15283 diff --git a/examples/desktop/screenshots/scatter_cmap.png b/examples/desktop/screenshots/scatter_cmap.png index 7f0bba38a..87a6e0ded 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:e9aba2f37c7682d68569e1bac7afac5f243afb98ab94d9957de4b59f9d3dd1c0 -size 57257 +oid sha256:a02d2b5d4735d656d1b754ac3681a7700d961d7e4a43dfaf3a7dd0d4f6516ba6 +size 37808 diff --git a/examples/desktop/screenshots/scatter_colorslice.png b/examples/desktop/screenshots/scatter_colorslice.png index 27249e63e..cede76dfd 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:39c49529552d6ace3d67b37f0c660e9734fcb763bdc165484f356ad8cffc908e -size 25218 +oid sha256:f7956e02d6c231bab091adb4ce9102ad4943050ccf171a0594a899a381880771 +size 14712 diff --git a/examples/desktop/screenshots/scatter_dataslice.png b/examples/desktop/screenshots/scatter_dataslice.png index 155510885..7a1429663 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:20757e215c4c208e08027f8e2b798691f421ce7662dc86be3615dc41084686f3 -size 27392 +oid sha256:0ecc6454dd197e6a3f146d0a04881db91b099673b9d74903536ca103b2418c89 +size 15657 diff --git a/examples/desktop/screenshots/scatter_present.png b/examples/desktop/screenshots/scatter_present.png index 87685fe90..08bc610b3 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:7a8ceb8f3d7203f0569374993784f2229448ace08b0abee94910e6ae71ceca29 -size 24587 +oid sha256:bd072918f21ed0ce4ea4e1f4499ec1ff66d867cfdc0ecd6b3ed8092141cd348e +size 14195 diff --git a/examples/desktop/screenshots/scatter_size.png b/examples/desktop/screenshots/scatter_size.png index afe8a0b35..056d2a531 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:a184ce0a202bc03fa61b3f4149109e44160bfd326c26f46db3b83ce0cf1699a6 -size 67710 +oid sha256:5ccfbac94de6ba122ea420dce58e4a576b2d58d9282aaf8d64de399278df57b3 +size 38076 diff --git a/examples/notebooks/image_widget_test.ipynb b/examples/notebooks/image_widget_test.ipynb index 90747757c..c236ce9b7 100644 --- a/examples/notebooks/image_widget_test.ipynb +++ b/examples/notebooks/image_widget_test.ipynb @@ -23,7 +23,9 @@ "metadata": {}, "outputs": [], "source": [ - "from nb_test_utils import plot_test, notebook_finished " + "from nb_test_utils import plot_test, notebook_finished\n", + "import nb_test_utils\n", + "nb_test_utils.TOLERANCE = 0.035" ] }, { @@ -57,7 +59,8 @@ "source": [ "iw = ImageWidget(\n", " data=a,\n", - " cmap=\"viridis\"\n", + " cmap=\"viridis\",\n", + " grid_plot_kwargs={\"size\": (900, 600)},\n", ")" ] }, @@ -128,7 +131,8 @@ "iw_movie = ImageWidget(\n", " data=gray_movie, \n", " slider_dims=[\"t\"],\n", - " cmap=\"gray\"\n", + " cmap=\"gray\",\n", + " grid_plot_kwargs={\"size\": (900, 600)},\n", ")" ] }, @@ -271,6 +275,9 @@ "execution_count": null, "id": "76535d56-e514-4c16-aa48-a6359f8019d5", "metadata": { + "jupyter": { + "source_hidden": true + }, "tags": [] }, "outputs": [], @@ -280,6 +287,7 @@ " window_funcs={\"t\": (np.mean, 5)},\n", " names=[f\"plane-{i}\" for i in range(n_planes)],\n", " cmap=\"gnuplot2\", \n", + " grid_plot_kwargs={\"size\": (900, 600)},\n", ")" ] }, @@ -379,6 +387,7 @@ " data=zfish_data, # you can also provide a list of tzxy arrays\n", " window_funcs={\"t\": (np.mean, 5)},\n", " cmap=\"gnuplot2\", \n", + " grid_plot_kwargs={\"size\": (900, 600)},\n", ")" ] }, @@ -444,6 +453,14 @@ "source": [ "notebook_finished()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8fff1a6-119e-4f03-ba3a-4c7b9e8c212b", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -462,7 +479,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.3" } }, "nbformat": 4, diff --git a/examples/notebooks/nb_test_utils.py b/examples/notebooks/nb_test_utils.py index 71d2d5114..90b7158ad 100644 --- a/examples/notebooks/nb_test_utils.py +++ b/examples/notebooks/nb_test_utils.py @@ -16,11 +16,73 @@ os.makedirs(SCREENSHOTS_DIR, exist_ok=True) os.makedirs(DIFFS_DIR, exist_ok=True) +TOLERANCE = 0.025 # store all the failures to allow the nb to proceed to test other examples FAILURES = list() +# TODO: consolidate testing functions into one module so we don't have this separate one for notebooks + +def rgba_to_rgb(img: np.ndarray) -> np.ndarray: + black = np.zeros(img.shape).astype(np.uint8) + black[:, :, -1] = 255 + + img_alpha = img[..., -1] / 255 + + rgb = img[..., :-1] * img_alpha[..., None] + black[..., :-1] * np.ones( + img_alpha.shape + )[..., None] * (1 - img_alpha[..., None]) + + return rgb.round().astype(np.uint8) + + +# image comparison functions from: https://github.com/pygfx/image-comparison +def image_similarity(src, target, threshold=0.2): + """Compute normalized RMSE 0..1 and decide if similar based on threshold. + + For every pixel, the euclidian distance between RGB values is computed, + and normalized by the maximum possible distance (between black and white). + The RMSE is then computed from those errors. + + The normalized RMSE is used to compute the + similarity metric, so larger errors (euclidian distance + between two RGB colors) will have a disproportionately + larger effect on the score than smaller errors. + + In other words, lots of small errors will lead to a good score + (closer to 0) whereas a few large errors will lead to a bad score + (closer to 1). + """ + float_type = np.float64 + src = np.asarray(src, dtype=float_type) + target = np.asarray(target, dtype=float_type) + denom = np.sqrt(np.mean(src * src)) + mse = np.mean((src - target) ** 2) + rmse = np.sqrt(mse) / denom + + similar = bool(rmse < threshold) + return similar, rmse + + +def normalize_image(img): + """Discard the alpha channel and convert from 0..255 uint8 to 0..1 float.""" + assert len(img.shape) == 3 + + # normalize to 0..1 range + if img.dtype == "u1" or np.max(img) > 1: + img = img / 255 + assert np.min(img) >= 0 and np.max(img) <= 1 + + # discard alpha channel + # unsupported if it's not fully opaque + if img.shape[-1] == 4: + assert np.max(img[..., 3]) == 1 + img = img[..., :-1] + + return img + + def _run_tests(): if "FASTPLOTLIB_NB_TESTS" not in os.environ.keys(): return False @@ -34,16 +96,15 @@ def _run_tests(): def plot_test(name, plot: Union[Plot, GridPlot]): if not _run_tests(): return + snapshot = plot.canvas.snapshot() + rgb_img = rgba_to_rgb(snapshot.data) if "REGENERATE_SCREENSHOTS" in os.environ.keys(): if os.environ["REGENERATE_SCREENSHOTS"] == "1": - regenerate_screenshot(name, snapshot.data) + regenerate_screenshot(name, rgb_img) - try: - assert_screenshot_equal(name, snapshot.data) - except AssertionError: - FAILURES.append(name) + assert_screenshot_equal(name, rgb_img) def regenerate_screenshot(name, data): @@ -53,13 +114,17 @@ def regenerate_screenshot(name, data): def assert_screenshot_equal(name, data): ground_truth = iio.imread(SCREENSHOTS_DIR.joinpath(f"nb-{name}.png")) - is_similar = np.allclose(data, ground_truth) + img = normalize_image(data) + ref_img = normalize_image(ground_truth) - update_diffs(name, is_similar, data, ground_truth) + similar, rmse = image_similarity(img, ref_img, threshold=TOLERANCE) - assert is_similar, ( - f"notebook snapshot for {name} has changed" - ) + update_diffs(name, similar, data, ground_truth) + + if not similar: + FAILURES.append( + (name, rmse) + ) def update_diffs(name, is_similar, img, ground_truth): @@ -81,7 +146,6 @@ def get_diffs_rgba(slicer): # split into an rgb and an alpha diff diffs = { DIFFS_DIR.joinpath(f"nb-diff-{name}-rgb.png"): slice(0, 3), - DIFFS_DIR.joinpath(f"nb-diff-{name}-alpha.png"): 3, } for path, slicer in diffs.items(): diff --git a/examples/notebooks/screenshots/nb-astronaut.png b/examples/notebooks/screenshots/nb-astronaut.png index 2faf79def..378260288 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:4845a61b99f7a489ac82a8688cc3350ce66e4771bb1399354591fd39688a58a2 -size 127977 +oid sha256:e584533ea04b9758634ba62dceeb72991861c509d01dc082436c54c272686409 +size 112104 diff --git a/examples/notebooks/screenshots/nb-astronaut_RGB.png b/examples/notebooks/screenshots/nb-astronaut_RGB.png index 22b2627cb..bf11bf667 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:2c34bd21fd7bf98bab25431019e8fee30b0f4912b6b4495ad963fb9e107b1f21 -size 125479 +oid sha256:db9602a610f258803d74ac03cd46447dd5a7ad62241ec26a4c3df30c1d6de299 +size 110408 diff --git a/examples/notebooks/screenshots/nb-camera.png b/examples/notebooks/screenshots/nb-camera.png index 32e83f3ba..9db4005bc 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:8ce695e954332a9b9122d418645d785900506fc30a897844bdf7fdce0bffb316 -size 89342 +oid sha256:4bb9080b99c2717e093bf6ae4986bf0689a8d377e137a7022c9c6929b9a335d3 +size 77965 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 a728df223..5be8f55a3 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:794d4ba4e31884a95c5a98596d142aa2d2af75647c5ad73dc573ff18493c1a07 -size 31256 +oid sha256:66a310e312add59a310ff0a50335db97ac557d7f2967d8251a7d811c25a4de28 +size 40517 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 index 8e624128e..8572f6472 100644 --- a/examples/notebooks/screenshots/nb-image-widget-movie-single-0-reset.png +++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-0-reset.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edd99517550a035ee55fb81301fb1c3e08e3e90bc4345e781449d83fa307a8a9 -size 62630 +oid sha256:ff83d6bab26b9bbccf66ed100764ffdfc7556f4cb04f0b85f50c2497ba0ab257 +size 134419 diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-0.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-0.png index 8e624128e..8572f6472 100644 --- a/examples/notebooks/screenshots/nb-image-widget-movie-single-0.png +++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edd99517550a035ee55fb81301fb1c3e08e3e90bc4345e781449d83fa307a8a9 -size 62630 +oid sha256:ff83d6bab26b9bbccf66ed100764ffdfc7556f4cb04f0b85f50c2497ba0ab257 +size 134419 diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-279.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-279.png index d27e49568..e241ce5a6 100644 --- a/examples/notebooks/screenshots/nb-image-widget-movie-single-279.png +++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-279.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d5f5889af4490cdc81a47fd8235493bdf0384a015edcb5177ffea274efb64b1 -size 72626 +oid sha256:337a22f11649b350f7f47d68d82be165633caeb7f8cef581e50f981d6ec0c52c +size 169615 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 index 12dce091c..b827fc536 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec662212f6299cd27c3e26bb6b9fa1a99b4dd2808934536640e2f54d8bf8f699 -size 63968 +oid sha256:22ff3ed815fcbe8bc95c321c806a4b42536e7014209cd43ac597a5ccefd8b9c6 +size 149261 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 index 44ccb8020..d37f44a3a 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffe73fa414fa1af8e2daa0bdb7fa75fd47d9d575b60c729a9426deb42225bb5a -size 54513 +oid sha256:11143f73a297d0b59c92db1b115ceac1bc1304135a9925302e616a4fd3669b25 +size 125012 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 index f0354cbb2..46d3fa9b3 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10d82b8d15a5d1099f8a909401d78cc6a87d22708a7cd4c32d96bb316d570da3 -size 50431 +oid sha256:7438018c3b55d423f57c42a9d03c1af6d5de168a2dfa5df9d535ef2ae1f1c8e9 +size 113981 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 index 25b65bd48..6146a7985 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79776dadbe6947e9f20c96e5dc2d6ee718100f24fc09579609e7b25614869b74 -size 65150 +oid sha256:9b57a1e6640de9471540fa4d86faadb706d6de8cc1de6a29fb65d709b91eef1e +size 146429 diff --git a/examples/notebooks/screenshots/nb-image-widget-movie-single-50.png b/examples/notebooks/screenshots/nb-image-widget-movie-single-50.png index 25b65bd48..6146a7985 100644 --- a/examples/notebooks/screenshots/nb-image-widget-movie-single-50.png +++ b/examples/notebooks/screenshots/nb-image-widget-movie-single-50.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79776dadbe6947e9f20c96e5dc2d6ee718100f24fc09579609e7b25614869b74 -size 65150 +oid sha256:9b57a1e6640de9471540fa4d86faadb706d6de8cc1de6a29fb65d709b91eef1e +size 146429 diff --git a/examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png b/examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png index 75fa3ef5a..b8bf7adeb 100644 --- a/examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png +++ b/examples/notebooks/screenshots/nb-image-widget-single-gnuplot2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e292d6e43e7a98cb72ca077e62bbc9ad3acde4753098ea2248c66ee07a9fc46 -size 143675 +oid sha256:dbfa1e7aeb7f0a068a33f2f11023a06f834332f7b3d8e4cf97b51222536fd6cb +size 434782 diff --git a/examples/notebooks/screenshots/nb-image-widget-single.png b/examples/notebooks/screenshots/nb-image-widget-single.png index 1321d01bb..86119e247 100644 --- a/examples/notebooks/screenshots/nb-image-widget-single.png +++ b/examples/notebooks/screenshots/nb-image-widget-single.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50f17ab342efff0d1d3bc06f36d2b7b372eed4426e282ffa2b12e3e7dc913b68 -size 134516 +oid sha256:7ceee2cdd73092cb84b4b0f2876fc08d838b8a47bb94d431a6c19c8a4793a153 +size 403521 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 index 2543f9a5d..82cee281f 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5834c92427c08b210a0971667018b4a63fd4e8d916bb02a582ba352cb0d5aad7 -size 64281 +oid sha256:47e3e6cea0e738b2731060488886606f05595cfdfb0d81e6db1aa099dc8e3a84 +size 148181 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 index 1a062cdf7..0b7832eee 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00f8173e7476a781826617bbaf03241348cece3c25d355e13832961cb022145f -size 50155 +oid sha256:0af4ceb50ed269aa80667c3012a871c87f73777cd8cb497ebb243b53932b9bad +size 72377 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 index 00af23a9a..2bc2db3a5 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:676217864c9f5ca4792c08a4b51574acdceb8c02b186e467633583b358bdb0f8 -size 121420 +oid sha256:9053c70da35fd42fe44a76e0ace8788ba79667b33c596409ca1e1f2f6d6ba3ad +size 195906 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 index bd31b760d..d5999dd0f 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bb119d1e38ec69285092c551da7ff12541a15c4ef144689e6535c520e0e988b -size 76596 +oid sha256:77d4a8542a5507e3eda1203a6da29a2f533bbbe2988ad297948c74e44a4337ec +size 177152 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 index ccbbd13d6..29af0398d 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57202d813c24f93fc106a1e66edd04af5b877ebf291380b3894b583ddccbda19 -size 72288 +oid sha256:3422923039d45b20ea6150f0ad545bdf876596ba60b156df5ec4004590a29a3e +size 139029 diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png index d4020153c..bb07b8fbb 100644 --- a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png +++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-50.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc156be2788a1d82f587a1ae0a7b29f4b6d75f07bfd83055ecefe92b213c01fd -size 56749 +oid sha256:ba9e055298372238ce0cd0c5ac4d75db8cd53f3f4acffbcc22bf7d503b40ec57 +size 79174 diff --git a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png index 368c1b9f8..6e8274659 100644 --- a/examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png +++ b/examples/notebooks/screenshots/nb-image-widget-zfish-frame-99.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:03da34d72c3437de1bebea5a545e1a75fb7b6a7ea309cbd88340031acc5cb852 -size 45223 +oid sha256:c6aed15f9f1b6bae442687613c5b04621f42e78f1dbda1e3560b000d652ba0b3 +size 61523 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 index c722c8ec1..28704bd2d 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:309384b0062003c9af321a005ddb5e0a78db382cf2b40285dd8ca43423cb13dd -size 74975 +oid sha256:499fab9183f2528297fdfa3c96a25eb58b2376a44556d790ef06928e0379af3a +size 174612 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 index 9be3a311f..d163fd22a 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28291e3913c28a2933affa12810254627f352fd4059a77d3637e2756737d11c0 -size 75617 +oid sha256:72832b86f802ee90b4eb54cb64d64aff59527fe0c7dcb87a4d8ab281ad15726b +size 142136 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 index 912374687..52ebd8591 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c248700a71fb8284d039714d9b11672f6788bcd0df716c26aa936436c5035c28 -size 116784 +oid sha256:b414fbb8f6935901b65851de9c7cb37df628d7b24759dc7f407ee130389216a3 +size 371687 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 index 66971bfb1..6c406a621 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5fe9fce8c8e63e497b558370d0d3edd8f86b0ad27939feec02715dd84fe7353 -size 75550 +oid sha256:e0ef52156509f308d972533fb45509ba7451b4d6149400d519aae28274609e41 +size 212053 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 index 76f6c71a2..aaed804b8 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7d563033c432006b88adce07aabf0ab6a2c6559b519f6f820ebb58066f4d1b2 -size 79214 +oid sha256:8fd94e597074094dc3718153c8bb94fb0b1bf58e58e34601e5c7281f938f52bd +size 200278 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 index 90639b14f..3110fa7cf 100644 --- a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50.png +++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-50.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8408e6e841d09b4c2f1704803515c878cdc46e4f7d4cd67b1634efb4efba8e98 -size 82327 +oid sha256:76ab21314fbd7846c1b94aeeed9ef7b97be99d2f2f7f09c13c0474a889c21179 +size 159319 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 index 97e3787ea..0cfad54e7 100644 --- a/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-99.png +++ b/examples/notebooks/screenshots/nb-image-widget-zfish-grid-frame-99.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c21bbd9a9d1548d5480f9a0f0f6d4ace0abfd80e4d09e295557163310c7095d -size 79733 +oid sha256:77f247de5374a8cb7ce27a338ab8be880d53d9586b52f646b400901ba70be3aa +size 146217 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 index 24eda7928..c74807939 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b6222d1a7291609f5d2637e97e9455a4e734b6dca4d6ebf9246ea46f32ce4de -size 81628 +oid sha256:33c3dfa77bbc558493634ab83fd1539ef76022a2e20d10e1353d2bd0a0e94a2c +size 183739 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 index 3285e7875..a2841b1d5 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6f5d03a9929a12232628da3a0c89673a650c94737ead73bf74e0daa587e75f9 -size 65977 +oid sha256:715f7909db0d374c2e618bb41f7a6341a8cc8891b1e3e8678a6f934fd71159a4 +size 127129 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 index 63bd3d070..9064f2323 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:182410c74215dc70140561200cdb414555e98a1ea7767205764a19cc9b72bf6d -size 66489 +oid sha256:76708e8e6e6865d700aa5286fca4d58ba4eb91f21ab3b0243bb128e9a84f063c +size 131192 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 index e82e34241..1fbaec974 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59eaa00b1ba39188f664719964036857df5cb143e2f70171d86e822958e98fa7 -size 62617 +oid sha256:51c62474b9ebee76242ef82a710a83b90e0183792790f6a2cd00213642b76755 +size 99519 diff --git a/examples/notebooks/screenshots/nb-imagewidget.png b/examples/notebooks/screenshots/nb-imagewidget.png new file mode 100644 index 000000000..9acfdb0f9 --- /dev/null +++ b/examples/notebooks/screenshots/nb-imagewidget.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f7a4a260ef4f9f2bdee9adab4ed376147cff39fcdd2f07eaf6e87e8b899f7d3 +size 89842 diff --git a/examples/notebooks/screenshots/nb-lines-3d.png b/examples/notebooks/screenshots/nb-lines-3d.png index 4ac6b8b92..a3b75de58 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:467cf0f08f6861c9556a412ed57e0bc6ff4499e62d576fa10dcdc2ca9ef4de6a -size 23693 +oid sha256:677f544d93cf7a733003c38666f555f0b598d41b92681dd2f09e6c11faa4aed0 +size 14186 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 0c875da24..0d9ff5729 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:c870f3010432310ba6d1937410a23836de6ddb656eb83bfb1b928d7d1211bd09 -size 17263 +oid sha256:0d981d57d7905879ab68af95da84d2cf530a9a40dc4d0ffb138119a11f4966be +size 11808 diff --git a/examples/notebooks/screenshots/nb-lines-cmap-jet-values.png b/examples/notebooks/screenshots/nb-lines-cmap-jet-values.png index e193c85b3..dbcbf1e7f 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:5c98af9372102a7fef96fe45650ca7e0b4f6e3589abd5fc3c1205130f3613c08 -size 18859 +oid sha256:706bffa485dd7994a70602ef2076aee79e1206dd508fbac903549fce526087b6 +size 13095 diff --git a/examples/notebooks/screenshots/nb-lines-cmap-jet.png b/examples/notebooks/screenshots/nb-lines-cmap-jet.png index acc52de78..6a3ae0c1c 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:bf3494a4cc2d4ea061fbd3465bd2133120b63bab6b248681307687e4e8e395a2 -size 16322 +oid sha256:cfd3f55e1671ac1fa45a8eb26aeb425ccb8d1ac033f5766f4002fee4380b2a77 +size 11174 diff --git a/examples/notebooks/screenshots/nb-lines-cmap-tab-10.png b/examples/notebooks/screenshots/nb-lines-cmap-tab-10.png index d18cadb51..9bb368e0e 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:b66364f0b7ba1da27b713e48cc757215f84143f6646451e8dfe7938d90a69102 -size 14863 +oid sha256:338dbcdf1a87266eee33367bfa08bcaec7eac42ef2dd928bbc699b3a0412ebaf +size 9889 diff --git a/examples/notebooks/screenshots/nb-lines-cmap-viridis-values.png b/examples/notebooks/screenshots/nb-lines-cmap-viridis-values.png index ecdbb0db7..23137bdf3 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:2e1b04f1ffc5c63dd93c9676bbf751f8ca698e113ce3403534f40ab868421960 -size 14974 +oid sha256:e36a7a74ac39dac5ac96a4e7c8e56990794ab1cda1b8ee5276087e9814dd1696 +size 10100 diff --git a/examples/notebooks/screenshots/nb-lines-cmap-viridis.png b/examples/notebooks/screenshots/nb-lines-cmap-viridis.png index a78bd9d54..2fcd4749c 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:69166f21efd52253b2b8444c32c9770a87983b3f21afcf49f4d0a94c51e5280c -size 19206 +oid sha256:b12ee5e31f64415b57536c59587b91c7a3a7c74e95be3459d8036a43d073d7db +size 13821 diff --git a/examples/notebooks/screenshots/nb-lines-cmap-white.png b/examples/notebooks/screenshots/nb-lines-cmap-white.png index c61050a7d..397b5fc94 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:1556f875c6e5538ca289db5ced0e59530174d899d6baa19876e1ad753571d4d1 -size 12921 +oid sha256:6239f23d3b5c1745879f5706352abb905d5638522b171776bff051e511426c2f +size 8359 diff --git a/examples/notebooks/screenshots/nb-lines-colors.png b/examples/notebooks/screenshots/nb-lines-colors.png index 33a751e98..149321e52 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:fb407b2008cb7a6793e7e53d487b959e1178de2a3b7fbd504b8ef3b92a7b09ea -size 40842 +oid sha256:9a5e99c5a872d9bbf8dd909498459ddee7f22f08d3fe3cd68b3ea57c105ab51b +size 27634 diff --git a/examples/notebooks/screenshots/nb-lines-data.png b/examples/notebooks/screenshots/nb-lines-data.png index 7447b5b86..9ed38b1f5 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:3fe83c11993dc99085526e11db60ac6797756b2b35145458009b36e56991a0d9 -size 55297 +oid sha256:cc0d3d6819ce0d9f5d531276bbde0397ef35e3084ac1f9b3575f0209eea07456 +size 39512 diff --git a/examples/notebooks/screenshots/nb-lines-underlay.png b/examples/notebooks/screenshots/nb-lines-underlay.png index 692aa76ea..d4b3d9f6d 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:f65834683f945ae52612fa1ae8415d25866ccd6d776dd94798b30b08769b0387 -size 56338 +oid sha256:9b12c8f29436be8d17c38f420120ab3d54b0eee9bef751eea2f99d01b1a8fa43 +size 50761 diff --git a/examples/notebooks/screenshots/nb-lines.png b/examples/notebooks/screenshots/nb-lines.png index b89e9f47c..603f4a8fc 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:cc0511ba508333566c902a3f1a902e76044a33a41f75bfc43ee158ff5b7bd6c7 -size 37671 +oid sha256:eeef2c47e7dde62038307fa7929a306801bf8b708fbcf1062ed9c751727bfb2b +size 24300 diff --git a/examples/tests/test_examples.py b/examples/tests/test_examples.py index 876533fa6..a570b4f36 100644 --- a/examples/tests/test_examples.py +++ b/examples/tests/test_examples.py @@ -1,6 +1,7 @@ """ Test that examples run without error. """ + import importlib import runpy import pytest @@ -8,6 +9,7 @@ import numpy as np import imageio.v3 as iio + from .testutils import ( ROOT, examples_dir, @@ -15,7 +17,11 @@ find_examples, wgpu_backend, is_lavapipe, - diffs_dir + diffs_dir, + generate_diff, + image_similarity, + normalize_image, + prep_for_write, ) # run all tests unless they opt-out @@ -52,7 +58,12 @@ def test_that_we_are_on_lavapipe(): def test_example_screenshots(module, force_offscreen): """Make sure that every example marked outputs the expected.""" # (relative) module name from project root - module_name = module.relative_to(ROOT/"examples").with_suffix("").as_posix().replace("/", ".") + module_name = ( + module.relative_to(ROOT / "examples") + .with_suffix("") + .as_posix() + .replace("/", ".") + ) # import the example module example = importlib.import_module(module_name) @@ -69,20 +80,35 @@ def test_example_screenshots(module, force_offscreen): screenshot_path = screenshots_dir / f"{module.stem}.png" + black = np.zeros(img.shape).astype(np.uint8) + black[:, :, -1] = 255 + + img_alpha = img[..., -1] / 255 + + rgb = img[..., :-1] * img_alpha[..., None] + black[..., :-1] * np.ones( + img_alpha.shape + )[..., None] * (1 - img_alpha[..., None]) + + rgb = rgb.round().astype(np.uint8) + if "REGENERATE_SCREENSHOTS" in os.environ.keys(): if os.environ["REGENERATE_SCREENSHOTS"] == "1": - iio.imwrite(screenshot_path, img) - #np.save(screenshot_path, img) + iio.imwrite(screenshot_path, rgb) assert ( screenshot_path.exists() ), "found # test_example = true but no reference screenshot available" - #stored_img = np.load(screenshot_path) - stored_img = iio.imread(screenshot_path) - is_similar = np.allclose(img, stored_img, atol=1) - update_diffs(module.stem, is_similar, img, stored_img) - assert is_similar, ( - f"rendered image for example {module.stem} changed, see " + + ref_img = iio.imread(screenshot_path) + + rgb = normalize_image(rgb) + ref_img = normalize_image(ref_img) + + similar, rmse = image_similarity(rgb, ref_img, threshold=0.025) + + update_diffs(module.stem, similar, rgb, ref_img) + assert similar, ( + f"diff {rmse} above threshold for {module.stem}, see " f"the {diffs_dir.relative_to(ROOT).as_posix()} folder" " for visual diffs (you can download this folder from" " CI build artifacts as well)" @@ -110,7 +136,6 @@ def get_diffs_rgba(slicer): # split into an rgb and an alpha diff diffs = { diffs_dir / f"diff-{module}-rgb.png": slice(0, 3), - diffs_dir / f"diff-{module}-alpha.png": 3, } for path, slicer in diffs.items(): diff --git a/examples/tests/testutils.py b/examples/tests/testutils.py index 5f6772fb7..f62ae7602 100644 --- a/examples/tests/testutils.py +++ b/examples/tests/testutils.py @@ -7,6 +7,8 @@ import sys from itertools import chain +import numpy as np + ROOT = Path(__file__).parents[2] # repo root examples_dir = ROOT / "examples" / "desktop" @@ -65,3 +67,189 @@ def find_examples(query=None, negative_query=None, return_stems=False): result = [r.stem for r in result] return result + +# image comparison functions from: https://github.com/pygfx/image-comparison +def image_similarity(src, target, threshold=0.2): + """Compute normalized RMSE 0..1 and decide if similar based on threshold. + + For every pixel, the euclidian distance between RGB values is computed, + and normalized by the maximum possible distance (between black and white). + The RMSE is then computed from those errors. + + The normalized RMSE is used to compute the + similarity metric, so larger errors (euclidian distance + between two RGB colors) will have a disproportionately + larger effect on the score than smaller errors. + + In other words, lots of small errors will lead to a good score + (closer to 0) whereas a few large errors will lead to a bad score + (closer to 1). + """ + float_type = np.float64 + src = np.asarray(src, dtype=float_type) + target = np.asarray(target, dtype=float_type) + denom = np.sqrt(np.mean(src * src)) + mse = np.mean((src - target) ** 2) + rmse = np.sqrt(mse) / denom + + similar = bool(rmse < threshold) + return similar, rmse + + +def normalize_image(img): + """Discard the alpha channel and convert from 0..255 uint8 to 0..1 float.""" + assert len(img.shape) == 3 + + # normalize to 0..1 range + if img.dtype == "u1" or np.max(img) > 1: + img = img / 255 + assert np.min(img) >= 0 and np.max(img) <= 1 + + # discard alpha channel + # unsupported if it's not fully opaque + if img.shape[-1] == 4: + assert np.max(img[..., 3]) == 1 + img = img[..., :-1] + + return img + + +def prep_for_write(img): + """Convert 0..1 float back to 0..255 uint8.""" + assert len(img.shape) == 3 + assert np.min(img) >= 0 and np.max(img) <= 1 + if img.dtype != "u1": + img = np.round(img * 255).astype("u1") + return img + + +def rescale_arr(arr, min, max): + """ + histogram rescale utility function + e.g. if the values are 0.3..0.7 + they are rescaled to min..max + """ + return np.interp(arr, (arr.min(), arr.max()), (min, max)) + + +def rgb_to_hls(rgb): + """ + convert rgb to hls + assumes input ranges are 0..1 + returns values in range 0..1 + + vectorized version of colorsys.rgb_to_hls + """ + maxc = np.max(rgb, axis=-1) + minc = np.min(rgb, axis=-1) + hls = np.empty_like(rgb) + l = (minc + maxc) / 2.0 # noqa: E741 + + with np.errstate(invalid="ignore"): + mask = l <= 0.5 + idx = np.where(mask) + hls[(*idx, 2)] = (maxc[idx] - minc[idx]) / (maxc[idx] + minc[idx]) + + idx = np.where(~mask) + hls[(*idx, 2)] = (maxc[idx] - minc[idx]) / (2.0 - maxc[idx] - minc[idx]) + + maxc_minc = maxc - minc + rc = (maxc - rgb[..., 0]) / maxc_minc + gc = (maxc - rgb[..., 1]) / maxc_minc + bc = (maxc - rgb[..., 2]) / maxc_minc + + mask1 = rgb[..., 0] == maxc + idx = np.where(mask1) + hls[(*idx, 0)] = bc[idx] - gc[idx] + + mask2 = rgb[..., 1] == maxc + idx = np.where(~mask1 & mask2) + hls[(*idx, 0)] = 2.0 + rc[idx] - bc[idx] + + idx = np.where(~mask1 & ~mask2) + hls[(*idx, 0)] = 4.0 + gc[idx] - rc[idx] + + hls[..., 0] = (hls[..., 0] / 6.0) % 1.0 + + idx = np.where(minc == maxc) + hls[idx] = 0.0 + hls[..., 1] = l + + return hls + + +def hls_to_rgb(hls): + """ + convert hls to rgb + assumes input ranges are 0..1 + returns values in range 0..1 + + vectorized version of colorsys.hls_to_rgb + """ + rgb = np.empty_like(hls) + + m2 = np.empty_like(hls[..., 1]) + mask = hls[..., 1] <= 0.5 + idx = np.where(mask) + m2[idx] = hls[(*idx, 1)] * (1.0 + hls[(*idx, 2)]) + idx = np.where(~mask) + m2[idx] = hls[(*idx, 1)] + hls[(*idx, 2)] - (hls[(*idx, 1)] * hls[(*idx, 2)]) + m1 = 2.0 * hls[..., 1] - m2 + + h1 = (hls[..., 0] + 1 / 3) % 1.0 + h2 = hls[..., 0] % 1.0 + h3 = (hls[..., 0] - 1 / 3) % 1.0 + + for i, h in enumerate([h1, h2, h3]): + mask1 = h < 1 / 6 + idx = np.where(mask1) + rgb[(*idx, i)] = m1[idx] + (m2[idx] - m1[idx]) * h[idx] * 6.0 + + mask2 = h < 0.5 + idx = np.where(~mask1 & mask2) + rgb[(*idx, i)] = m2[idx] + + mask3 = h < 2 / 3 + idx = np.where(~mask1 & ~mask2 & mask3) + rgb[(*idx, i)] = m1[idx] + (m2[idx] - m1[idx]) * ((2 / 3) - h[idx]) * 6.0 + + idx = np.where(~mask1 & ~mask2 & ~mask3) + rgb[(*idx, i)] = m1[idx] + + return rgb + + +def generate_diff(src, target, fuzz=0.05): + """ + Generate an image that + highlights the differences between src and target image + any pixels with a euclidian color distance < fuzz will be ignored + fuzz is expressed as a percentage of the maximum possible distance + which is the distance between (0,0,0) and (1,1,1) = sqrt(3). + """ + # compute euclidian distance between pixels + # and normalize to 0..1 + max_dist = np.linalg.norm([1, 1, 1], axis=-1) + error = np.linalg.norm(np.abs(target - src), axis=-1) / max_dist + # apply fuzz + error_idx = np.where(error > fuzz) + + diff_img_hls = rgb_to_hls(target) + # lighten the whole image + diff_img_hls[..., 1] = rescale_arr(diff_img_hls[..., 1], 0.25, 1.0) + diff_img_hls[..., 1] **= 0.2 + # reduce the color saturation + diff_img_hls[..., 2] = rescale_arr(diff_img_hls[..., 2], 0.0, 0.75) + diff_img_hls[..., 2] **= 2 + + # make the diff pixels red + diff_img_hls[(*error_idx, 0)] = 0 + # give them the same lighting level + diff_img_hls[(*error_idx, 1)] = 0.5 + # saturate based on the error + diff_img_hls[(*error_idx, 2)] = 0.5 + error[error_idx] * 0.5 + + # convert back to rgb + diff_img = hls_to_rgb(diff_img_hls) + + return diff_img