From 185a83dafadd056e0a7c6ac1aa92134ebccb6a3f Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 28 Jun 2023 14:52:23 -0400 Subject: [PATCH 1/5] handling empty subplots in image widget --- fastplotlib/widgets/image.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index 80d4868ce..360d720a1 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -1,3 +1,4 @@ +import weakref from typing import * from warnings import warn from functools import partial @@ -89,11 +90,13 @@ def gridplot(self) -> GridPlot: return self._gridplot @property - def managed_graphics(self): + def managed_graphics(self) -> List[weakref.proxy]: """List of ``ImageWidget`` managed graphics.""" iw_managed = list() for subplot in self.gridplot: - iw_managed.append(subplot["image_widget_managed"]) + # empty subplots will not have any image widget data + if len(subplot.graphics) > 0: + iw_managed.append(subplot["image_widget_managed"]) return iw_managed @property From fd811c0bff2aac026b44e3147913fa2b3452e0c7 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 28 Jun 2023 15:00:52 -0400 Subject: [PATCH 2/5] fix toolbar to work with 2dim xy data --- fastplotlib/widgets/image.py | 53 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index 360d720a1..2b196365f 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -940,33 +940,38 @@ def __init__(self, iw: ImageWidget): tooltip="reset vmin/vmax", ) - self.step_size_setter = BoundedIntText( - value=1, - min=1, - max=self.iw.sliders["t"].max, - step=1, - description="Step Size:", - disabled=False, - description_tooltip="set slider step", - layout=Layout(width="150px"), - ) - self.play_button = Play( - value=0, - min=iw.sliders["t"].min, - max=iw.sliders["t"].max, - step=iw.sliders["t"].step, - description="play/pause", - disabled=False, - ) + if self.iw.ndim == 2: + self.widget = HBox([self.reset_vminvmax_button]) + else: - self.widget = HBox( - [self.reset_vminvmax_button, self.play_button, self.step_size_setter] - ) + self.step_size_setter = BoundedIntText( + value=1, + min=1, + max=self.iw.sliders["t"].max, + step=1, + description="Step Size:", + disabled=False, + description_tooltip="set slider step", + layout=Layout(width="150px"), + ) + self.play_button = Play( + value=0, + min=iw.sliders["t"].min, + max=iw.sliders["t"].max, + step=iw.sliders["t"].step, + description="play/pause", + disabled=False, + ) + + self.widget = HBox( + [self.reset_vminvmax_button, self.play_button, self.step_size_setter] + ) + + self.step_size_setter.observe(self.change_stepsize, "value") + jslink((self.play_button, "value"), (self.iw.sliders["t"], "value")) + jslink((self.play_button, "max"), (self.iw.sliders["t"], "max")) self.reset_vminvmax_button.on_click(self.reset_vminvmax) - self.step_size_setter.observe(self.change_stepsize, "value") - jslink((self.play_button, "value"), (self.iw.sliders["t"], "value")) - jslink((self.play_button, "max"), (self.iw.sliders["t"], "max")) def reset_vminvmax(self, obj): if len(self.iw.vmin_vmax_sliders) != 0: From 4e09ab03dad8410ceb3b56775a4240ea6f79a9ec Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 28 Jun 2023 19:26:55 -0400 Subject: [PATCH 3/5] add code comments --- fastplotlib/widgets/image.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index 2b196365f..86476be3a 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -940,8 +940,10 @@ def __init__(self, iw: ImageWidget): tooltip="reset vmin/vmax", ) + # only for xy data, no time point slider needed if self.iw.ndim == 2: self.widget = HBox([self.reset_vminvmax_button]) + # for txy, tzxy, etc. data else: self.step_size_setter = BoundedIntText( From 7ba5cdea4284b222a72c700e63ce65744c9e2b7d Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 28 Jun 2023 20:14:17 -0400 Subject: [PATCH 4/5] update image widget notebook to have xy data --- examples/notebooks/image_widget.ipynb | 223 +++++++++++--------------- 1 file changed, 92 insertions(+), 131 deletions(-) diff --git a/examples/notebooks/image_widget.ipynb b/examples/notebooks/image_widget.ipynb index f50d83d36..5b7de6145 100644 --- a/examples/notebooks/image_widget.ipynb +++ b/examples/notebooks/image_widget.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "04f453ca-d0bc-411f-b2a6-d38294dd0a26", "metadata": { "tags": [] @@ -13,6 +13,74 @@ "import numpy as np" ] }, + { + "cell_type": "markdown", + "id": "bd632552-dba1-4e48-b8b2-595da7757d0f", + "metadata": {}, + "source": [ + "# Single image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c798a5e0-07a0-4468-8e22-9b53b8243ab5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "a = np.random.rand(512, 512)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b0dbf913-c1c6-4c2a-8191-45a87b2ce310", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "iw = ImageWidget(\n", + " data=a,\n", + " vmin_vmax_sliders=True,\n", + " cmap=\"viridis\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8264fd19-661f-4c50-bdb4-d3998ffd5ff5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "iw.show()" + ] + }, + { + "cell_type": "markdown", + "id": "b718162f-9aa6-4091-a7a4-c620676b48bd", + "metadata": {}, + "source": [ + "### can dynamically change features" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "393375df-327c-409a-9e3e-75121a0df6cb", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "iw.gridplot[0, 0].graphics[0].cmap = \"gnuplot2\"" + ] + }, { "cell_type": "markdown", "id": "e933771b-f172-4fa9-b2f8-129723efb808", @@ -23,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "ea87f9a6-437f-41f6-8739-c957fb04bdbf", "metadata": { "tags": [] @@ -35,27 +103,12 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "8b7a6066-ff69-4bee-bae6-160fb4038393", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5ccfeea584fb491b9431b9284ab45993", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "iw = ImageWidget(\n", " data=a, \n", @@ -67,28 +120,12 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "3d4cb44e-2c71-4bff-aeed-b2129f34d724", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "8624f2dba4d94e5881879d14464cd370", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(VBox(children=(JupyterWgpuCanvas(), HBox(children=(Button(icon='expand-arrows-alt', layout=Layo…" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "iw.show()" ] @@ -105,7 +142,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "id": "f278b26a-1b71-4e76-9cc7-efaddbd7b122", "metadata": { "tags": [] @@ -118,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "id": "cb4d4b7c-919f-41c0-b1cc-b4496473d760", "metadata": { "tags": [] @@ -131,7 +168,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "2eea6432-4d38-4d42-ab75-f6aa1bab36f4", "metadata": { "tags": [] @@ -144,7 +181,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "id": "afa2436f-2741-49d6-87f6-7a91a343fe0e", "metadata": { "tags": [] @@ -165,7 +202,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "id": "370d1d24-2944-491f-9da0-fa0c7ed073ef", "metadata": { "tags": [] @@ -186,7 +223,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "882162eb-c873-42df-a945-d5e05ad141c9", "metadata": { "tags": [] @@ -199,27 +236,12 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "bf9f92b6-38ad-4d78-b88c-a32d473b6462", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "befbd479926a4195ad6ee395da0aaa89", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "iw = ImageWidget(\n", " data=data, \n", @@ -242,28 +264,12 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "403dde31-981a-46fb-b005-1bcef19c4f2c", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "48534008501f483b865c8df4de77e204", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(VBox(children=(JupyterWgpuCanvas(), HBox(children=(Button(icon='expand-arrows-alt', layout=Layo…" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "iw.show()" ] @@ -278,26 +284,12 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "b59d95e2-9092-4915-beef-01661d164781", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "text/plain": [ - "two: Subplot @ 0x7f362c02e350\n", - " parent: None\n", - " Graphics:\n", - "\t'image': ImageGraphic @ 0x7f362c0f69d0" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "iw.gridplot[\"two\"]" ] @@ -312,7 +304,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "a8f070db-da11-4062-95aa-f19b96351ee8", "metadata": { "tags": [] @@ -332,27 +324,12 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "b1587410-a08e-484c-8795-195a413d6374", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "11be69e0a3c1411792cd25548c0ed273", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "dims = (256, 256, 5, 100)\n", "data = [np.random.rand(*dims) for i in range(4)]\n", @@ -370,28 +347,12 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "3ccea6c6-9580-4720-bce8-a5507cf867a3", "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "95b68c9c58754953a8a3e92980973bd6", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(VBox(children=(JupyterWgpuCanvas(), HBox(children=(Button(icon='expand-arrows-alt', layout=Layo…" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "iw.show()" ] @@ -406,7 +367,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "fd4433a9-2add-417c-a618-5891371efae0", "metadata": { "tags": [] From 6883bf26c03ab724baad9ca578c57675f6d4ee4f Mon Sep 17 00:00:00 2001 From: Kushal Kolar Date: Wed, 28 Jun 2023 20:55:35 -0400 Subject: [PATCH 5/5] Update fastplotlib/widgets/image.py --- fastplotlib/widgets/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index 86476be3a..85ef9be15 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -90,7 +90,7 @@ def gridplot(self) -> GridPlot: return self._gridplot @property - def managed_graphics(self) -> List[weakref.proxy]: + def managed_graphics(self) -> List[ImageGraphic]: """List of ``ImageWidget`` managed graphics.""" iw_managed = list() for subplot in self.gridplot: