From 2c00596dda23b2da98c86d75603a38c05652e9e1 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Sun, 11 Dec 2022 21:25:32 -0500 Subject: [PATCH 01/19] beginning base logic for interactivity impl --- fastplotlib/graphics/_base.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index 69fb66066..aa3507fb5 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -68,3 +68,29 @@ def __repr__(self): else: return f"fastplotlib.{self.__class__.__name__} @ {hex(id(self))}" +class Interaction: + # make them abstract properties + @property + def indices(self) -> Any: + pass + + @indices.setter + def indices(self, indices: Any): + pass + + @property + def features(self) -> List[str]: + pass + + def _set_feature(self, name: str, new_data: Any, indices: Any): + pass + + def link(self, event: str, feature: Any, feature_data: Any, target: Graphic, target_feature: Any, target_data: Any, indices_mapper: Any): + # event occurs, causes change in feature of current graphic to data indices from pick_info, + # also causes change in target graphic to target feature at target data with corresponding or mapped + # indices based on the indice_mapper function + + # indice mapper takes in source features and maps to target features + pass + + From 10aeca8934ee8b7c67066d82050c68003ed15731 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Sun, 11 Dec 2022 21:38:43 -0500 Subject: [PATCH 02/19] further changes and ideas --- fastplotlib/graphics/_base.py | 10 +++++++++- fastplotlib/graphics/heatmap.py | 22 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index aa3507fb5..b4c0a1b9b 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -5,6 +5,7 @@ from fastplotlib.utils import get_colors, map_labels_to_colors +from abc import ABC, abstractmethod class Graphic: def __init__( @@ -68,28 +69,35 @@ def __repr__(self): else: return f"fastplotlib.{self.__class__.__name__} @ {hex(id(self))}" -class Interaction: +class Interaction(ABC): # make them abstract properties @property + @abstractmethod def indices(self) -> Any: pass @indices.setter + @abstractmethod def indices(self, indices: Any): pass @property + @abstractmethod def features(self) -> List[str]: pass + @abstractmethod def _set_feature(self, name: str, new_data: Any, indices: Any): pass + @abstractmethod def link(self, event: str, feature: Any, feature_data: Any, target: Graphic, target_feature: Any, target_data: Any, indices_mapper: Any): # event occurs, causes change in feature of current graphic to data indices from pick_info, # also causes change in target graphic to target feature at target data with corresponding or mapped # indices based on the indice_mapper function + # events can be feature changes, when feature changes want to trigger an event + # indice mapper takes in source features and maps to target features pass diff --git a/fastplotlib/graphics/heatmap.py b/fastplotlib/graphics/heatmap.py index 9f065fafd..4eb9950a2 100644 --- a/fastplotlib/graphics/heatmap.py +++ b/fastplotlib/graphics/heatmap.py @@ -1,10 +1,15 @@ import numpy as np import pygfx from typing import * + +from fastplotlib.graphics._base import Graphic + from .image import ImageGraphic from ..utils import quick_min_max, get_cmap_texture +from ._base import Interaction + default_selection_options = { "mode": "single", @@ -40,7 +45,22 @@ def __init__( self.callbacks = callbacks -class HeatmapGraphic(ImageGraphic): +class HeatmapGraphic(ImageGraphic, Interaction): + @property + def indices(self) -> Any: + pass + + @property + def features(self) -> List[str]: + pass + + def _set_feature(self, name: str, new_data: Any, indices: Any): + pass + + def link(self, event: str, feature: Any, feature_data: Any, target: Graphic, target_feature: Any, target_data: Any, + indices_mapper: Any): + pass + def __init__( self, data: np.ndarray, From f19c9c1db727fefdb2f9375cc5da785d7c6df2d8 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Tue, 13 Dec 2022 22:29:15 -0500 Subject: [PATCH 03/19] wip --- fastplotlib/graphics/line.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index a972f952d..fbf751340 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -1,5 +1,6 @@ import numpy as np import pygfx +from typing import * from ._base import Graphic @@ -24,6 +25,8 @@ def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, co material=material(thickness=size, vertex_colors=True) ) + self.events = {} + def fix_data(self): # TODO: data should probably be a property of any Graphic?? Or use set_data() and get_data() if self.data.ndim == 1: @@ -53,3 +56,32 @@ def update_colors(self, colors: np.ndarray): self.world_object.geometry.colors.data[:] = self.colors self.world_object.geometry.colors.update_range() + + @property + def indices(self) -> Any: + return self.indices + + @property + def features(self) -> List[str]: + return self.features + + def _set_feature(self, name: str, new_data: Any, indices: Any): + if name == "color": + self.update_colors(new_data) + elif name == "data": + self.update_data(new_data) + else: + raise ValueError("name arg is not a valid feature") + + def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): + valid_events = ["click"] + if event in valid_events: + self.world_object.add_event_handler(self.event_handler, event) + self.events[event] = list() + self.events[event].append((target, feature, new_data)) + else: + raise ValueError("event not possible") + + def event_handler(self, event): + for event in self.events[event]: + event[0]._set_feature(name=event[1], new_data=event[2], indices=None) From ac6c67a5a8207d4910fca9233212d264e72295a3 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 14 Dec 2022 21:18:59 -0500 Subject: [PATCH 04/19] grrrrr --- examples/lineplot.ipynb | 2 +- fastplotlib/graphics/line.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/lineplot.ipynb b/examples/lineplot.ipynb index 63ddd9ade..9383df848 100644 --- a/examples/lineplot.ipynb +++ b/examples/lineplot.ipynb @@ -186,7 +186,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.9.2" } }, "nbformat": 4, diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index fbf751340..94c7e3809 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -4,7 +4,6 @@ from ._base import Graphic - class LineGraphic(Graphic): def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, colors: np.ndarray = None, cmap: str = None, *args, **kwargs): super(LineGraphic, self).__init__(data, colors=colors, cmap=cmap, *args, **kwargs) @@ -77,11 +76,16 @@ def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices valid_events = ["click"] if event in valid_events: self.world_object.add_event_handler(self.event_handler, event) - self.events[event] = list() - self.events[event].append((target, feature, new_data)) else: raise ValueError("event not possible") + if event in self.events.keys(): + self.events[event].append((target, feature, new_data)) + else: + self.events[event] = list() + self.events[event].append((target, feature, new_data)) + def event_handler(self, event): - for event in self.events[event]: - event[0]._set_feature(name=event[1], new_data=event[2], indices=None) + if event.type in self.events.keys(): + for target_info in self.events[event.type]: + target_info[0]._set_feature(name=target_info[1], new_data=target_info[2], indices=None) From ad6a8d6a83be81db87537d7e74230413e349a047 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 14 Dec 2022 21:25:49 -0500 Subject: [PATCH 05/19] oops --- examples/event_single_contour.ipynb | 225 ++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 examples/event_single_contour.ipynb diff --git a/examples/event_single_contour.ipynb b/examples/event_single_contour.ipynb new file mode 100644 index 000000000..dcb23a9e2 --- /dev/null +++ b/examples/event_single_contour.ipynb @@ -0,0 +1,225 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2d14adc9-1ba0-4a5c-ab7d-d31d5fad238d", + "metadata": {}, + "source": [ + "# working on event interactivity for a single contour" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "a934868b-3792-48da-83e7-793350545a09", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4420c0dc-23f9-4405-bc0b-b2b745061326", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-12-14 21:15:10.071022: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "2022-12-14 21:15:10.183652: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", + "2022-12-14 21:15:10.196607: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-14 21:15:10.196623: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", + "2022-12-14 21:15:10.703225: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-14 21:15:10.703287: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-14 21:15:10.703292: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from fastplotlib.plot import Plot\n", + "from fastplotlib.graphics import LineGraphic\n", + "import pygfx\n", + "import pickle\n", + "from mesmerize_core import *\n", + "import tifffile" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "3eb77356-5314-4004-ac26-0628a19c038b", + "metadata": {}, + "outputs": [], + "source": [ + "contours = pickle.load(open(\"/home/caitlin/Downloads/contours.pickle\", \"rb\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0b2090b9-9fe6-407e-b517-2b8b28d38d2e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "155" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(contours)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "90373974-c3a1-468e-8cf2-8c31061284a6", + "metadata": {}, + "outputs": [], + "source": [ + "single_contour = LineGraphic(data=contours[0], size=10.0)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "df16cf45-a767-40ce-a1f5-efac891b57f5", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "15944fb7c4d34bd28fa6ef1a73965b1d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "RFBOutputContext()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "MESA-INTEL: warning: Performance support disabled, consider sysctl dev.i915.perf_stream_paranoid=0\n", + "\n" + ] + } + ], + "source": [ + "plot = Plot()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "038eb7d8-f4cf-4d0e-8aa5-1e52c65d0fe3", + "metadata": {}, + "outputs": [], + "source": [ + "plot.add_graphic(single_contour)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c6ffada3-4b52-4a54-815e-d07581240433", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
initial snapshot
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1ad382c3d2c94b3bae8b66a0be34e7f7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "JupyterWgpuCanvas()" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "73ab4a53-f26b-4668-8603-eba027449d82", + "metadata": {}, + "outputs": [], + "source": [ + "red = np.array([1.0, 1.0, 1.0, 1.0]) " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "3803b5d4-0c1e-4b0d-803c-7bb769a310d2", + "metadata": {}, + "outputs": [], + "source": [ + "single_contour.link(event=\"click\", target=single_contour, feature=\"color\", new_data=red)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba6339e2-247a-4ae6-b2a7-0f105c2511c9", + "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.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 95e77a142f8afb38ea320bcdde8f5b51814448fc Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 14 Dec 2022 21:46:51 -0500 Subject: [PATCH 06/19] reorg --- fastplotlib/graphics/_base.py | 15 +++++++++++++-- fastplotlib/graphics/line.py | 17 +++++++++-------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index b4c0a1b9b..86f094052 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, List import numpy as np import pygfx @@ -6,6 +6,7 @@ from fastplotlib.utils import get_colors, map_labels_to_colors from abc import ABC, abstractmethod +from dataclasses import dataclass class Graphic: def __init__( @@ -91,7 +92,7 @@ def _set_feature(self, name: str, new_data: Any, indices: Any): pass @abstractmethod - def link(self, event: str, feature: Any, feature_data: Any, target: Graphic, target_feature: Any, target_data: Any, indices_mapper: Any): + def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): # event occurs, causes change in feature of current graphic to data indices from pick_info, # also causes change in target graphic to target feature at target data with corresponding or mapped # indices based on the indice_mapper function @@ -101,4 +102,14 @@ def link(self, event: str, feature: Any, feature_data: Any, target: Graphic, tar # indice mapper takes in source features and maps to target features pass + @abstractmethod + def event_handler(self, event): + pass +@dataclass +class EventData: + """Class for keeping track of the info necessary for interactivity after event occurs.""" + def __init__(self, target: Graphic, feature: str, new_data: Any): + self.target = target + self.feature = feature + self.new_data = new_data diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index 94c7e3809..d036b6873 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -3,6 +3,7 @@ from typing import * from ._base import Graphic +from ._base import EventData class LineGraphic(Graphic): def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, colors: np.ndarray = None, cmap: str = None, *args, **kwargs): @@ -24,7 +25,7 @@ def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, co material=material(thickness=size, vertex_colors=True) ) - self.events = {} + self.registered_callbacks = {} def fix_data(self): # TODO: data should probably be a property of any Graphic?? Or use set_data() and get_data() @@ -79,13 +80,13 @@ def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices else: raise ValueError("event not possible") - if event in self.events.keys(): - self.events[event].append((target, feature, new_data)) + if event in self.registered_callbacks.keys(): + self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data)) else: - self.events[event] = list() - self.events[event].append((target, feature, new_data)) + self.registered_callbacks[event] = list() + self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data)) def event_handler(self, event): - if event.type in self.events.keys(): - for target_info in self.events[event.type]: - target_info[0]._set_feature(name=target_info[1], new_data=target_info[2], indices=None) + if event.type in self.registered_callbacks.keys(): + for target_info in self.registered_callbacks[event.type]: + target_info.target._set_feature(name=target_info.feature, new_data=target_info.new_data, indices=None) From 71eb48f56f00f190e0e3ab62bdad4bee3c76cc2c Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Wed, 14 Dec 2022 22:13:38 -0500 Subject: [PATCH 07/19] small changes and reorg --- fastplotlib/graphics/_base.py | 16 ++++++++++------ fastplotlib/graphics/line.py | 11 ++--------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index 86f094052..64a87acbc 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -1,4 +1,4 @@ -from typing import Any, List +from typing import * import numpy as np import pygfx @@ -22,6 +22,7 @@ def __init__( self.colors = None self.name = name + self.registered_callbacks = dict() # if colors_length is None: # colors_length = self.data.shape[0] @@ -70,6 +71,12 @@ def __repr__(self): else: return f"fastplotlib.{self.__class__.__name__} @ {hex(id(self))}" + def event_handler(self, event): + if event.type in self.registered_callbacks.keys(): + for target_info in self.registered_callbacks[event.type]: + target_info.target._set_feature(name=target_info.feature, new_data=target_info.new_data, + indices=target_info.indices) + class Interaction(ABC): # make them abstract properties @property @@ -102,14 +109,11 @@ def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices # indice mapper takes in source features and maps to target features pass - @abstractmethod - def event_handler(self, event): - pass - @dataclass class EventData: """Class for keeping track of the info necessary for interactivity after event occurs.""" - def __init__(self, target: Graphic, feature: str, new_data: Any): + def __init__(self, target: Graphic, feature: str, new_data: Any, indices: Any): self.target = target self.feature = feature self.new_data = new_data + self.indices = indices diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index d036b6873..e79b11813 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -25,8 +25,6 @@ def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, co material=material(thickness=size, vertex_colors=True) ) - self.registered_callbacks = {} - def fix_data(self): # TODO: data should probably be a property of any Graphic?? Or use set_data() and get_data() if self.data.ndim == 1: @@ -81,12 +79,7 @@ def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices raise ValueError("event not possible") if event in self.registered_callbacks.keys(): - self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data)) + self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data, indices=None)) else: self.registered_callbacks[event] = list() - self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data)) - - def event_handler(self, event): - if event.type in self.registered_callbacks.keys(): - for target_info in self.registered_callbacks[event.type]: - target_info.target._set_feature(name=target_info.feature, new_data=target_info.new_data, indices=None) + self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data, indices=None)) From e203cff1bf75c23196dbad00b41e0780bb0e3b6f Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Sat, 17 Dec 2022 12:24:06 -0500 Subject: [PATCH 08/19] updates to line, works w previous example --- fastplotlib/graphics/_base.py | 22 ++++++---------------- fastplotlib/graphics/line.py | 32 +++++++++++++++----------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index 64a87acbc..5d992fd55 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -71,14 +71,7 @@ def __repr__(self): else: return f"fastplotlib.{self.__class__.__name__} @ {hex(id(self))}" - def event_handler(self, event): - if event.type in self.registered_callbacks.keys(): - for target_info in self.registered_callbacks[event.type]: - target_info.target._set_feature(name=target_info.feature, new_data=target_info.new_data, - indices=target_info.indices) - class Interaction(ABC): - # make them abstract properties @property @abstractmethod def indices(self) -> Any: @@ -100,20 +93,17 @@ def _set_feature(self, name: str, new_data: Any, indices: Any): @abstractmethod def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): - # event occurs, causes change in feature of current graphic to data indices from pick_info, - # also causes change in target graphic to target feature at target data with corresponding or mapped - # indices based on the indice_mapper function - - # events can be feature changes, when feature changes want to trigger an event - - # indice mapper takes in source features and maps to target features pass + def event_handler(self, event): + if event.type in self.registered_callbacks.keys(): + for target_info in self.registered_callbacks[event.type]: + target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data) + @dataclass class EventData: """Class for keeping track of the info necessary for interactivity after event occurs.""" - def __init__(self, target: Graphic, feature: str, new_data: Any, indices: Any): + def __init__(self, target: Graphic, feature: str, new_data: Any): self.target = target self.feature = feature self.new_data = new_data - self.indices = indices diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index e79b11813..5197e92ab 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -2,10 +2,9 @@ import pygfx from typing import * -from ._base import Graphic -from ._base import EventData +from ._base import Graphic, EventData, Interaction -class LineGraphic(Graphic): +class LineGraphic(Graphic, Interaction): def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, colors: np.ndarray = None, cmap: str = None, *args, **kwargs): super(LineGraphic, self).__init__(data, colors=colors, cmap=cmap, *args, **kwargs) @@ -57,29 +56,28 @@ def update_colors(self, colors: np.ndarray): @property def indices(self) -> Any: - return self.indices + return None @property def features(self) -> List[str]: - return self.features + return None - def _set_feature(self, name: str, new_data: Any, indices: Any): - if name == "color": - self.update_colors(new_data) - elif name == "data": - self.update_data(new_data) + def _set_feature(self, feature: str, new_data: Any, indices: Any = None): + if feature in ["colors", "data"]: + update_func = getattr(self, f"update_{feature}") + update_func(new_data) else: raise ValueError("name arg is not a valid feature") - def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): + def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): valid_events = ["click"] - if event in valid_events: - self.world_object.add_event_handler(self.event_handler, event) + if event_type in valid_events: + self.world_object.add_event_handler(self.event_handler, event_type) else: raise ValueError("event not possible") - if event in self.registered_callbacks.keys(): - self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data, indices=None)) + if event_type in self.registered_callbacks.keys(): + self.registered_callbacks[event_type].append(EventData(target=target, feature=feature, new_data=new_data)) else: - self.registered_callbacks[event] = list() - self.registered_callbacks[event].append(EventData(target=target, feature=feature, new_data=new_data, indices=None)) + self.registered_callbacks[event_type] = list() + self.registered_callbacks[event_type].append(EventData(target=target, feature=feature, new_data=new_data)) \ No newline at end of file From 0f2253170bf17d075dfc2c08ad78734d02e28a1d Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Sun, 18 Dec 2022 13:31:14 -0500 Subject: [PATCH 09/19] small changes --- fastplotlib/graphics/_base.py | 28 +++++++++++++++++++++------- fastplotlib/graphics/line.py | 16 +++------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index 5d992fd55..d731d68e4 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -88,22 +88,36 @@ def features(self) -> List[str]: pass @abstractmethod - def _set_feature(self, name: str, new_data: Any, indices: Any): + def _set_feature(self, feature: str, new_data: Any, indices: Any): pass @abstractmethod - def link(self, event: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): + def _reset_feature(self): pass + def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): + valid_events = ["click"] + if event_type in valid_events: + self.world_object.add_event_handler(self.event_handler, event_type) + else: + raise ValueError("event not possible") + + if event_type in self.registered_callbacks.keys(): + self.registered_callbacks[event_type].append( + CallbackData(target=target, feature=feature, new_data=new_data)) + else: + self.registered_callbacks[event_type] = list() + self.registered_callbacks[event_type].append( + CallbackData(target=target, feature=feature, new_data=new_data)) + def event_handler(self, event): if event.type in self.registered_callbacks.keys(): for target_info in self.registered_callbacks[event.type]: target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data) @dataclass -class EventData: +class CallbackData: """Class for keeping track of the info necessary for interactivity after event occurs.""" - def __init__(self, target: Graphic, feature: str, new_data: Any): - self.target = target - self.feature = feature - self.new_data = new_data + target: Graphic + feature: str + new_data: Any diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index 5197e92ab..157ac674a 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -2,7 +2,7 @@ import pygfx from typing import * -from ._base import Graphic, EventData, Interaction +from ._base import Graphic, CallbackData, Interaction class LineGraphic(Graphic, Interaction): def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, colors: np.ndarray = None, cmap: str = None, *args, **kwargs): @@ -69,15 +69,5 @@ def _set_feature(self, feature: str, new_data: Any, indices: Any = None): else: raise ValueError("name arg is not a valid feature") - def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): - valid_events = ["click"] - if event_type in valid_events: - self.world_object.add_event_handler(self.event_handler, event_type) - else: - raise ValueError("event not possible") - - if event_type in self.registered_callbacks.keys(): - self.registered_callbacks[event_type].append(EventData(target=target, feature=feature, new_data=new_data)) - else: - self.registered_callbacks[event_type] = list() - self.registered_callbacks[event_type].append(EventData(target=target, feature=feature, new_data=new_data)) \ No newline at end of file + def _reset_feature(): + pass \ No newline at end of file From 16922e72017c6469af52696f4ad8befec7cb2506 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Sun, 18 Dec 2022 13:33:24 -0500 Subject: [PATCH 10/19] git is so agitating sometimes --- fastplotlib/graphics/linecollection.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/fastplotlib/graphics/linecollection.py b/fastplotlib/graphics/linecollection.py index 67703be15..7d05b8e1d 100644 --- a/fastplotlib/graphics/linecollection.py +++ b/fastplotlib/graphics/linecollection.py @@ -1,11 +1,15 @@ import numpy as np import pygfx -from typing import Union +from typing import Union, List + +from fastplotlib.graphics._base import Graphic + from .line import LineGraphic from typing import * +from ._base import Interaction -class LineCollection(): +class LineCollection(Interaction): def __init__(self, data: List[np.ndarray], zlevel: Union[List[float], float] = None, size: Union[float, List[float]] = 2.0, colors: Union[List[np.ndarray], np.ndarray] = None, cmap: Union[List[str], str] = None, *args, **kwargs): @@ -47,6 +51,20 @@ def __init__(self, data: List[np.ndarray], zlevel: Union[List[float], float] = N self.collection.append(LineGraphic(d, _zlevel, _size, _colors, _cmap)) + @property + def indices(self) -> Any: + pass + + @property + def features(self) -> List[str]: + pass + + def _set_feature(self, feature: str, new_data: Any, indices: Any): + pass + + def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): + pass + def __getitem__(self, item): return self.collection[item] From 70a3be6de1e83e0b885c507bfbddb9acf8f259ec Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Mon, 19 Dec 2022 11:19:17 -0500 Subject: [PATCH 11/19] fixing z_position --- fastplotlib/graphics/line.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index 157ac674a..c1afa6fe8 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -5,10 +5,10 @@ from ._base import Graphic, CallbackData, Interaction class LineGraphic(Graphic, Interaction): - def __init__(self, data: np.ndarray, zlevel: float = None, size: float = 2.0, colors: np.ndarray = None, cmap: str = None, *args, **kwargs): + def __init__(self, data: np.ndarray, z_position: float = None, size: float = 2.0, colors: np.ndarray = None, cmap: str = None, *args, **kwargs): super(LineGraphic, self).__init__(data, colors=colors, cmap=cmap, *args, **kwargs) - self.zlevel = zlevel + self.z_position = z_position self.fix_data() @@ -33,11 +33,11 @@ def fix_data(self): if self.data.shape[1] != 2: raise ValueError("Must pass 1D, 2D or 3D data") # make it 2D with zlevel - if self.zlevel is None: - self.zlevel = 0 + if self.z_position is None: + self.z_position = 0 # zeros - zs = np.full(self.data.shape[0], fill_value=self.zlevel, dtype=np.float32) + zs = np.full(self.data.shape[0], fill_value=self.z_position, dtype=np.float32) self.data = np.dstack([self.data[:, 0], self.data[:, 1], zs])[0] From bc688fc510b28b115c478d9759059f85a695d1e4 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Mon, 19 Dec 2022 12:13:22 -0500 Subject: [PATCH 12/19] implementing reset_feature --- fastplotlib/graphics/_base.py | 11 +++++++---- fastplotlib/graphics/line.py | 9 +++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index d731d68e4..8d2942816 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -7,6 +7,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass +# from .linecollection import LineCollection class Graphic: def __init__( @@ -92,7 +93,7 @@ def _set_feature(self, feature: str, new_data: Any, indices: Any): pass @abstractmethod - def _reset_feature(self): + def _reset_feature(self, feature: str, old_data: Any, indices: Any): pass def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): @@ -104,16 +105,17 @@ def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, in if event_type in self.registered_callbacks.keys(): self.registered_callbacks[event_type].append( - CallbackData(target=target, feature=feature, new_data=new_data)) + CallbackData(target=target, feature=feature, new_data=new_data, old_data=getattr(target, feature).copy())) else: self.registered_callbacks[event_type] = list() self.registered_callbacks[event_type].append( - CallbackData(target=target, feature=feature, new_data=new_data)) + CallbackData(target=target, feature=feature, new_data=new_data, old_data=getattr(target, feature).copy())) def event_handler(self, event): if event.type in self.registered_callbacks.keys(): for target_info in self.registered_callbacks[event.type]: - target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data) + target_info.target._reset_feature(feature=target_info.feature, old_data=target_info.old_data, indices=None) + target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data, indices=None) @dataclass class CallbackData: @@ -121,3 +123,4 @@ class CallbackData: target: Graphic feature: str new_data: Any + old_data: Any diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index c1afa6fe8..307d93bb8 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -69,5 +69,10 @@ def _set_feature(self, feature: str, new_data: Any, indices: Any = None): else: raise ValueError("name arg is not a valid feature") - def _reset_feature(): - pass \ No newline at end of file + def _reset_feature(self, feature: str, old_data: Any, indices: Any = None): + if feature in ["colors", "data"]: + update_func = getattr(self, f"update_{feature}") + update_func(old_data) + else: + raise ValueError("name arg is not a valid feature") + From 24fb5a52deec009c0fe6a5305aff1280203b9922 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Mon, 19 Dec 2022 12:14:40 -0500 Subject: [PATCH 13/19] blah --- examples/event_handler.ipynb | 426 +++++++++++++++++++++++ examples/event_linecollection.ipynb | 455 +++++++++++++++++++++++++ examples/event_single_contour.ipynb | 181 ++++++++-- fastplotlib/graphics/heatmap.py | 6 +- fastplotlib/graphics/image.py | 20 +- fastplotlib/graphics/linecollection.py | 21 +- 6 files changed, 1078 insertions(+), 31 deletions(-) create mode 100644 examples/event_handler.ipynb create mode 100644 examples/event_linecollection.ipynb diff --git a/examples/event_handler.ipynb b/examples/event_handler.ipynb new file mode 100644 index 000000000..9c22e77a9 --- /dev/null +++ b/examples/event_handler.ipynb @@ -0,0 +1,426 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a0b458c1-53c6-43d9-a72a-41f51bfe493d", + "metadata": {}, + "source": [ + "### notebook for learning event handler system" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "638b6a65-6d78-459c-ac88-35312233d22a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-12-19 11:35:14.246180: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "2022-12-19 11:35:14.498269: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", + "2022-12-19 11:35:14.542615: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-19 11:35:14.542629: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", + "2022-12-19 11:35:15.350591: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-19 11:35:15.350720: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-19 11:35:15.350726: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" + ] + }, + { + "ename": "ImportError", + "evalue": "cannot import name 'Graphic' from partially initialized module 'fastplotlib.graphics._base' (most likely due to a circular import) (/home/caitlin/repos/fastplotlib/fastplotlib/graphics/_base.py)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[1], line 5\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mmatplotlib\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m pyplot \u001b[38;5;28;01mas\u001b[39;00m plt\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpandas\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mpd\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfastplotlib\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m GridPlot, Image, Plot, Line, Heatmap\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mscipy\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspatial\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m distance\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mipywidgets\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mwidgets\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m IntSlider, VBox\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Plot\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpathlib\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Path\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mwgpu\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgui\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mauto\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m run\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/plot.py:3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mwgpu\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgui\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mauto\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WgpuCanvas\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlayouts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_subplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Subplot\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m graphics\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfunctools\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m partial\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/layouts/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_gridplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m GridPlot\n\u001b[1;32m 3\u001b[0m __all__ \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 4\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGridPlot\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 5\u001b[0m ]\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/layouts/_gridplot.py:5\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_defaults\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m create_controller\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_subplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Subplot\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;241m*\u001b[39m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mwgpu\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgui\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mauto\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WgpuCanvas\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/layouts/_subplot.py:3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Scene, OrthographicCamera, PanZoomController, OrbitOrthoController, \\\n\u001b[1;32m 2\u001b[0m AxesHelper, GridHelper, WgpuRenderer, Background, BackgroundMaterial\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgraphics\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m HeatmapGraphic\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_defaults\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m create_camera, create_controller\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;241m*\u001b[39m\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mhistogram\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m HistogramGraphic\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mline\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LineGraphic\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mscatter\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ScatterGraphic\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/histogram.py:7\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mnumpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnp\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[0;32m----> 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_base\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Graphic\n\u001b[1;32m 10\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01m_HistogramBin\u001b[39;00m(pygfx\u001b[38;5;241m.\u001b[39mMesh):\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__int__\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/_base.py:10\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mabc\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ABC, abstractmethod\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mdataclasses\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m dataclass\n\u001b[0;32m---> 10\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlinecollection\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LineCollection\n\u001b[1;32m 12\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mGraphic\u001b[39;00m:\n\u001b[1;32m 13\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 15\u001b[0m data,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 20\u001b[0m name: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 21\u001b[0m ):\n", + "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/linecollection.py:5\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Union, List\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfastplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgraphics\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_base\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Graphic\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mline\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LineGraphic\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;241m*\u001b[39m\n", + "\u001b[0;31mImportError\u001b[0m: cannot import name 'Graphic' from partially initialized module 'fastplotlib.graphics._base' (most likely due to a circular import) (/home/caitlin/repos/fastplotlib/fastplotlib/graphics/_base.py)" + ] + } + ], + "source": [ + "from mesmerize_core import *\n", + "import numpy as np\n", + "from matplotlib import pyplot as plt\n", + "import pandas as pd\n", + "from fastplotlib import GridPlot, Image, Plot, Line, Heatmap\n", + "from scipy.spatial import distance\n", + "from ipywidgets.widgets import IntSlider, VBox\n", + "import pygfx" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "80938adc-1775-4751-94dd-89fb94ed673a", + "metadata": {}, + "outputs": [], + "source": [ + "class Contour_Selection():\n", + " def __init__(\n", + " self,\n", + " gp: GridPlot,\n", + " coms,\n", + " ):\n", + " self.gp = gp\n", + " self.heatmap = self.gp.subplots[0, 1].scene.children[0]\n", + " self.image = None\n", + " self._contour_index = None \n", + " \n", + " for child in self.gp.subplots[0, 0].scene.children:\n", + " if isinstance(child, pygfx.Image):\n", + " self.image = child\n", + " break;\n", + " if self.image == None:\n", + " raise ValueError(\"No image found!\")\n", + " self.coms = np.array(coms)\n", + " \n", + " self.image.add_event_handler(self.event_handler, \"click\")\n", + " \n", + " # first need to add event handler for when contour is clicked on\n", + " # should also trigger highlighting in heatmap\n", + " def event_handler(self, event):\n", + " if self._contour_index is not None:\n", + " self.remove_highlight()\n", + " self.add_highlight(event)\n", + " else:\n", + " self.add_highlight(event)\n", + " \n", + " def add_highlight(self, event):\n", + " click_location = np.array(event.pick_info[\"index\"])\n", + " self._contour_index = np.linalg.norm((self.coms - click_location), axis=1).argsort()[0] + 1\n", + " line = self.gp.subplots[0, 0].scene.children[self._contour_index]\n", + " line.geometry.colors.data[:] = np.array([1.0, 1.0, 1.0, 1.0]) \n", + " line.geometry.colors.update_range()\n", + " #self.heatmap.add_highlight(self._contour_index)\n", + " \n", + " def remove_highlight(self):\n", + " # change color of highlighted index back to normal\n", + " line = self.gp.subplots[0, 0].scene.children[self._contour_index]\n", + " line.geometry.colors.data[:] = np.array([1., 0., 0., 0.7]) \n", + " line.geometry.colors.update_range()\n", + " # for h in self.heatmap._highlights:\n", + " # self.heatmap.remove_highlight(h)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7b3129e6-5d82-4f39-b887-e584421c3a74", + "metadata": {}, + "outputs": [], + "source": [ + "set_parent_raw_data_path(\"/home/kushal/caiman_data/\")\n", + "\n", + "batch_path = \"/home/clewis7/caiman_data/cnmf_practice/batch.pickle\"\n", + "\n", + "movie_path = \"/home/kushal/caiman_data/example_movies/Sue_2x_3000_40_-46.tif\"" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "776c6dd8-cf07-47ee-bcc4-5fe84bc030f5", + "metadata": {}, + "outputs": [], + "source": [ + "df = load_batch(batch_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b22fd79b-5a7a-48fb-898c-4d3f3a34c118", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
algoitem_nameinput_movie_pathparamsoutputscommentsuuid
0mcorrmy_movieexample_movies/Sue_2x_3000_40_-46.tif{'main': {'max_shifts': (24, 24), 'strides': (...{'mean-projection-path': 1ed8feb3-9fc8-4a78-8f...None1ed8feb3-9fc8-4a78-8f6d-164620822016
1cnmfmy_movie1ed8feb3-9fc8-4a78-8f6d-164620822016/1ed8feb3-...{'main': {'fr': 30, 'p': 1, 'nb': 2, 'merge_th...{'mean-projection-path': 5f4e3e27-ac1f-4ede-90...None5f4e3e27-ac1f-4ede-903b-be43bd81fddc
\n", + "
" + ], + "text/plain": [ + " algo item_name input_movie_path \\\n", + "0 mcorr my_movie example_movies/Sue_2x_3000_40_-46.tif \n", + "1 cnmf my_movie 1ed8feb3-9fc8-4a78-8f6d-164620822016/1ed8feb3-... \n", + "\n", + " params \\\n", + "0 {'main': {'max_shifts': (24, 24), 'strides': (... \n", + "1 {'main': {'fr': 30, 'p': 1, 'nb': 2, 'merge_th... \n", + "\n", + " outputs comments \\\n", + "0 {'mean-projection-path': 1ed8feb3-9fc8-4a78-8f... None \n", + "1 {'mean-projection-path': 5f4e3e27-ac1f-4ede-90... None \n", + "\n", + " uuid \n", + "0 1ed8feb3-9fc8-4a78-8f6d-164620822016 \n", + "1 5f4e3e27-ac1f-4ede-903b-be43bd81fddc " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "03045957-837e-49e3-83aa-3e069af977a1", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3b283ef0f3084d828f80fd3a6cb25413", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "RFBOutputContext()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8b104ac5f10e4d53866953a4401593df", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(JupyterWgpuCanvas(), IntSlider(value=0, max=2999)))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "gp = GridPlot(shape=(1,2))\n", + "\n", + "contours, coms = df.iloc[-1].cnmf.get_contours()\n", + "movie = df.iloc[-1].cnmf.get_input_memmap()\n", + "temporal = df.iloc[-1].cnmf.get_temporal()\n", + "\n", + "contour_graphic = Image(movie[0].T, cmap=\"gnuplot2\")\n", + "heatmap = Heatmap(data=temporal[:,0:1000], cmap=\"jet\")\n", + "\n", + "slider = IntSlider(value=0, min=0, max=movie.shape[0] - 1, step=1)\n", + "\n", + "gp.subplots[0,0].add_graphic(contour_graphic)\n", + "gp.subplots[0,1].add_graphic(heatmap)\n", + "\n", + "for coor in contours:\n", + " # line data has to be 3D\n", + " zs = np.ones(coor.shape[0]) # this will place it above the image graphic\n", + " c3d = [coor[:, 0], coor[:, 1], zs]\n", + " coors_3d = np.dstack(c3d)[0]\n", + "\n", + " # make all the lines red, [R, G, B, A] array\n", + " colors = np.vstack([[1., 0., 0., 0.7]] * coors_3d.shape[0])\n", + " line_graphic = Line(data=coors_3d, colors=colors, zlevel=1)\n", + " gp.subplots[0, 0].add_graphic(line_graphic)\n", + "\n", + "previous_slider_value = 0\n", + "def update_frame(): \n", + " if slider.value == previous_slider_value:\n", + " return\n", + " contour_graphic.update_data(data=movie[slider.value].T)\n", + "\n", + "gp.add_animations([update_frame])\n", + "\n", + "VBox([gp.show(), slider])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2bf4a1ea-3559-4846-bc32-4dddaca2d470", + "metadata": {}, + "outputs": [], + "source": [ + "contour_selection = Contour_Selection(gp=gp, coms=coms)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "5ecdbdea-4e77-462f-a18d-5ed9b45faada", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(155, 3000)" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "temporal.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "51b3feea-af91-4158-97a2-8dbadd2480b5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "numpy.ndarray" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(coms[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "3b2011f4-046b-4396-a592-81a5128d2482", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([7.12861818, 9.84114483])" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "coms[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "c5791bf4-a116-4093-bce1-eee7bc25221c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gp.subplots[0, 1]" + ] + }, + { + "cell_type": "markdown", + "id": "ae9cce16-370f-44d2-b532-dc442cce379d", + "metadata": {}, + "source": [ + "next steps:\n", + " clicking on a contour should highlight it and the heatmap row" + ] + } + ], + "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.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/event_linecollection.ipynb b/examples/event_linecollection.ipynb new file mode 100644 index 000000000..ff23b623c --- /dev/null +++ b/examples/event_linecollection.ipynb @@ -0,0 +1,455 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9cba8fd1-5bd6-431b-a0d8-4fc671bbc631", + "metadata": {}, + "source": [ + "# working on interactivity for linecollection" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f5d95c3d-1260-4dd9-81de-e29356022046", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5733cb62-f688-450b-aa20-3fd1e994d729", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-12-18 14:41:24.532552: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "2022-12-18 14:41:24.625689: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", + "2022-12-18 14:41:24.628296: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-18 14:41:24.628306: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", + "2022-12-18 14:41:25.058487: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-18 14:41:25.058533: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-18 14:41:25.058537: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from fastplotlib.plot import Plot\n", + "from fastplotlib.graphics import LineGraphic, LineCollection, ImageGraphic\n", + "import pygfx\n", + "import pickle\n", + "from mesmerize_core import *\n", + "import tifffile" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "840d59ca-f3a6-4a32-8393-a1250ed40121", + "metadata": {}, + "outputs": [], + "source": [ + "contours = pickle.load(open(\"/home/caitlin/Downloads/contours.pickle\", \"rb\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1e769837-639e-4da8-953c-4b312a1096cb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "155" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(contours)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2f095853-3304-42d8-970e-c01db8cf8152", + "metadata": {}, + "outputs": [], + "source": [ + "line_collection = LineCollection(data=contours, size=5.0, cmap=\"jet\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b6dcf23c-21aa-46cb-8749-7fb298f2ace5", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c7bc183cce3a45c281d9868f3e055b3a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "RFBOutputContext()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "MESA-INTEL: warning: Performance support disabled, consider sysctl dev.i915.perf_stream_paranoid=0\n", + "\n" + ] + } + ], + "source": [ + "plot = Plot()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ed02c2f0-58f3-4e57-91b8-7f5b03759e97", + "metadata": {}, + "outputs": [], + "source": [ + "# create image to use for linking \n", + "data = np.ones((190, 200))\n", + "img = ImageGraphic(data=data)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "64404ac7-e33a-4bef-bae7-31488a730c39", + "metadata": {}, + "outputs": [], + "source": [ + "# add image first and use for handling image\n", + "for contour in line_collection:\n", + " plot.add_graphic(contour)\n", + "plot.add_graphic(img)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "921e0b11-de3d-4a0f-8035-3c1f1c562a5e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
initial snapshot
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9da3b15ceb03437e84d665975ca1c119", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "JupyterWgpuCanvas()" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "ccbf3a5b-f35e-4017-a751-404e0168e8e6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([10. , 10.0773941])" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "contours[0][0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8617453b-435b-4362-bd9e-6041f0004312", + "metadata": {}, + "outputs": [], + "source": [ + "coordinates = list()\n", + "coms = list()\n", + "\n", + "for contour in contours:\n", + " for coor in contour:\n", + " coor = coor[~np.isnan(coors).any(axis=1)]\n", + " coordinates.append(coor)\n", + "\n", + " com = coors.mean(axis=0)\n", + " coms.append(com)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b812c149-3c7a-41a8-922e-6bf133788066", + "metadata": {}, + "outputs": [], + "source": [ + "click_location = np.array(event.pick_info[\"index\"])\n", + "self._contour_index = np.linalg.norm((self.coms - click_location), axis=1).argsort()[0] + 1\n", + "\n", + "def indices_mapper(click_location: np.array, coms: List) -> int:\n", + " # should take in some params and then return the index of the contour that needs to be changed, color or data\n", + " # needs to take in the data of all the contours\n", + " # calculates the coms\n", + " # euclidean distance from pick info find the index \n", + " # return the index" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "037582e9-6bc1-474a-badc-126054abc82a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[fastplotlib.LineGraphic @ 0x7f59c5ff18e0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ff1cd0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ff1ca0,\n", + " fastplotlib.LineGraphic @ 0x7f59c6000b80,\n", + " fastplotlib.LineGraphic @ 0x7f59c600a340,\n", + " fastplotlib.LineGraphic @ 0x7f59c600ab20,\n", + " fastplotlib.LineGraphic @ 0x7f59c6013340,\n", + " fastplotlib.LineGraphic @ 0x7f59c6013b20,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f9c340,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f9cb20,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fa5340,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fa5b20,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fae340,\n", + " fastplotlib.LineGraphic @ 0x7f59c5faed00,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fb9790,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fbe220,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fbec70,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fc6700,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fce190,\n", + " fastplotlib.LineGraphic @ 0x7f59c5fcebe0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f55670,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f5d100,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f5db50,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f655e0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f6b070,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f6bac0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f73550,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f73fa0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f7ba30,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f834c0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f83f10,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f8c9a0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f94430,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f94e80,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f1a910,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f233a0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f23df0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f2b880,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f31310,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f31dc0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f38850,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f422e0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f42d30,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f4b7c0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f50250,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f50ca0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ed9730,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ede1c0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5edec10,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ee96a0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ef1130,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ef1b80,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ef7610,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f010a0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f01af0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f06580,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f06fd0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5f10a60,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e964f0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e96f40,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e9e9d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ea8460,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ea8eb0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5eae940,\n", + " fastplotlib.LineGraphic @ 0x7f59c5eb73d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5eb7e20,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ebe8b0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ec5340,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ec5d90,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ece820,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e562b0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e56d00,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e5d790,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e64220,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e64c70,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e6c700,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e75190,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e75be0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e7b670,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e83100,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e83b50,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e8d5e0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e94070,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e94ac0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e1b550,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e1bfa0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e21a30,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e2c4c0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e2cf10,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e339a0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e3b430,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e3be80,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e41910,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e4a3a0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e4adf0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e51880,\n", + " fastplotlib.LineGraphic @ 0x7f59c5dda310,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ddad60,\n", + " fastplotlib.LineGraphic @ 0x7f59c5de37f0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5de8280,\n", + " fastplotlib.LineGraphic @ 0x7f59c5de8cd0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5df1760,\n", + " fastplotlib.LineGraphic @ 0x7f59c5df71f0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5df7c40,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e006d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e09160,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e09bb0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5e10640,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d990d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d99b20,\n", + " fastplotlib.LineGraphic @ 0x7f59c5da05b0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5da7040,\n", + " fastplotlib.LineGraphic @ 0x7f59c5da7a90,\n", + " fastplotlib.LineGraphic @ 0x7f59c5daf520,\n", + " fastplotlib.LineGraphic @ 0x7f59c5daff70,\n", + " fastplotlib.LineGraphic @ 0x7f59c5db6a00,\n", + " fastplotlib.LineGraphic @ 0x7f59c5dbf490,\n", + " fastplotlib.LineGraphic @ 0x7f59c5dbfee0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5dc6970,\n", + " fastplotlib.LineGraphic @ 0x7f59c5dcf400,\n", + " fastplotlib.LineGraphic @ 0x7f59c5dcfe50,\n", + " fastplotlib.LineGraphic @ 0x7f59c5dd48e0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d5e370,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d5edc0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d66850,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d6c2e0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d6cd30,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d777c0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d7b280,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d7bcd0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d86760,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d8c1f0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d8cc40,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d166d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d1e160,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d1ebb0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d25640,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d2b0d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d2bb20,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d345b0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d3b070,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d3bac0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d45580,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d45fd0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d4ca60,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d534f0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d53f40,\n", + " fastplotlib.LineGraphic @ 0x7f59c5cdb9d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ce4460,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ce4eb0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5ceb940,\n", + " fastplotlib.LineGraphic @ 0x7f59c5cf13d0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5cf1e20,\n", + " fastplotlib.LineGraphic @ 0x7f59c5cfa8b0,\n", + " fastplotlib.LineGraphic @ 0x7f59c5d03340,\n", + " fastplotlib.ImageGraphic @ 0x7f5a5002d5b0]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# link image\n", + "img.link(event_type=\"click\", target=line_collection, feature=\"colors\", indices_mapper=indices_mapper)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f3659f8b-031c-475e-b265-7ebeebe858c9", + "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.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/event_single_contour.ipynb b/examples/event_single_contour.ipynb index dcb23a9e2..1174b040d 100644 --- a/examples/event_single_contour.ipynb +++ b/examples/event_single_contour.ipynb @@ -29,14 +29,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "2022-12-14 21:15:10.071022: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", + "2022-12-19 12:04:42.299047: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", - "2022-12-14 21:15:10.183652: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", - "2022-12-14 21:15:10.196607: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-14 21:15:10.196623: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", - "2022-12-14 21:15:10.703225: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-14 21:15:10.703287: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-14 21:15:10.703292: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" + "2022-12-19 12:04:42.399624: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", + "2022-12-19 12:04:42.402140: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-19 12:04:42.402151: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", + "2022-12-19 12:04:42.835552: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-19 12:04:42.835614: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", + "2022-12-19 12:04:42.835619: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" ] } ], @@ -88,19 +88,144 @@ "metadata": {}, "outputs": [], "source": [ - "single_contour = LineGraphic(data=contours[0], size=10.0)" + "single_contour = LineGraphic(data=contours[0], size=10.0, cmap=\"jet\")" ] }, { "cell_type": "code", "execution_count": 6, + "id": "a8e24de1-a3a7-4f6d-bdd8-b32f91a138e4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0. , 0. , 0.5 , 1. ],\n", + " [0. , 0. , 0.6604278 , 1. ],\n", + " [0. , 0. , 0.8386809 , 1. ],\n", + " [0. , 0. , 1. , 1. ],\n", + " [0. , 0.11176471, 1. , 1. ],\n", + " [0. , 0.26862746, 1. , 1. ],\n", + " [0. , 0.40980393, 1. , 1. ],\n", + " [0. , 0.56666666, 1. , 1. ],\n", + " [0. , 0.7235294 , 1. , 1. ],\n", + " [0. , 0.88039213, 0.9835547 , 1. ],\n", + " [0.11068944, 1. , 0.8570525 , 1. ],\n", + " [0.22454143, 1. , 0.7432005 , 1. ],\n", + " [0.35104364, 1. , 0.61669827, 1. ],\n", + " [0.47754586, 1. , 0.49019608, 1. ],\n", + " [0.6040481 , 1. , 0.36369386, 1. ],\n", + " [0.7305503 , 1. , 0.23719165, 1. ],\n", + " [0.84440225, 1. , 0.12333966, 1. ],\n", + " [0.97090447, 0.95933187, 0. , 1. ],\n", + " [1. , 0.8140886 , 0. , 1. ],\n", + " [1. , 0.6688453 , 0. , 1. ],\n", + " [1. , 0.523602 , 0. , 1. ],\n", + " [1. , 0.3928831 , 0. , 1. ],\n", + " [1. , 0.24763979, 0. , 1. ],\n", + " [1. , 0.10239651, 0. , 1. ],\n", + " [0.8565062 , 0. , 0. , 1. ],\n", + " [0.6782531 , 0. , 0. , 1. ],\n", + " [0.5 , 0. , 0. , 1. ]], dtype=float32)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "single_contour.colors" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ae0adaec-be96-4fe7-8aa5-07b3bb6b7c18", + "metadata": {}, + "outputs": [], + "source": [ + "feature = \"colors\"" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "30cfdbd9-0cc1-4aa2-81e4-c009e8f483ad", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0. , 0. , 0.5 , 1. ],\n", + " [0. , 0. , 0.6604278 , 1. ],\n", + " [0. , 0. , 0.8386809 , 1. ],\n", + " [0. , 0. , 1. , 1. ],\n", + " [0. , 0.11176471, 1. , 1. ],\n", + " [0. , 0.26862746, 1. , 1. ],\n", + " [0. , 0.40980393, 1. , 1. ],\n", + " [0. , 0.56666666, 1. , 1. ],\n", + " [0. , 0.7235294 , 1. , 1. ],\n", + " [0. , 0.88039213, 0.9835547 , 1. ],\n", + " [0.11068944, 1. , 0.8570525 , 1. ],\n", + " [0.22454143, 1. , 0.7432005 , 1. ],\n", + " [0.35104364, 1. , 0.61669827, 1. ],\n", + " [0.47754586, 1. , 0.49019608, 1. ],\n", + " [0.6040481 , 1. , 0.36369386, 1. ],\n", + " [0.7305503 , 1. , 0.23719165, 1. ],\n", + " [0.84440225, 1. , 0.12333966, 1. ],\n", + " [0.97090447, 0.95933187, 0. , 1. ],\n", + " [1. , 0.8140886 , 0. , 1. ],\n", + " [1. , 0.6688453 , 0. , 1. ],\n", + " [1. , 0.523602 , 0. , 1. ],\n", + " [1. , 0.3928831 , 0. , 1. ],\n", + " [1. , 0.24763979, 0. , 1. ],\n", + " [1. , 0.10239651, 0. , 1. ],\n", + " [0.8565062 , 0. , 0. , 1. ],\n", + " [0.6782531 , 0. , 0. , 1. ],\n", + " [0.5 , 0. , 0. , 1. ]], dtype=float32)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "getattr(single_contour, feature)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ba7765c1-5c2f-4898-a250-9894b11153c4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "single_contour.registered_callbacks" + ] + }, + { + "cell_type": "code", + "execution_count": 10, "id": "df16cf45-a767-40ce-a1f5-efac891b57f5", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "15944fb7c4d34bd28fa6ef1a73965b1d", + "model_id": "30efba9281ef4564a58a3b2a3cbcac73", "version_major": 2, "version_minor": 0 }, @@ -126,7 +251,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 11, "id": "038eb7d8-f4cf-4d0e-8aa5-1e52c65d0fe3", "metadata": {}, "outputs": [], @@ -136,14 +261,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 12, "id": "c6ffada3-4b52-4a54-815e-d07581240433", "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
initial snapshot
" + "
initial snapshot
" ], "text/plain": [ "" @@ -155,7 +280,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "1ad382c3d2c94b3bae8b66a0be34e7f7", + "model_id": "43085a939e61460395b69e5a19242f6d", "version_major": 2, "version_minor": 0 }, @@ -163,7 +288,7 @@ "JupyterWgpuCanvas()" ] }, - "execution_count": 8, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -174,28 +299,46 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 13, "id": "73ab4a53-f26b-4668-8603-eba027449d82", "metadata": {}, "outputs": [], "source": [ - "red = np.array([1.0, 1.0, 1.0, 1.0]) " + "white = np.ones(shape=single_contour.colors.shape)" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 14, "id": "3803b5d4-0c1e-4b0d-803c-7bb769a310d2", "metadata": {}, "outputs": [], "source": [ - "single_contour.link(event=\"click\", target=single_contour, feature=\"color\", new_data=red)" + "single_contour.link(event_type=\"click\", target=single_contour, feature=\"colors\", new_data=white)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e5cd5e4-da0b-465c-b46a-d6bd9b54f36d", + "metadata": {}, + "outputs": [], + "source": [ + "single_contour.registered_callbacks" ] }, { "cell_type": "code", "execution_count": null, - "id": "ba6339e2-247a-4ae6-b2a7-0f105c2511c9", + "id": "39c2362a-3fc7-49c7-8623-a5720720678c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42008ad7-cd12-4756-adb2-92cccafffda0", "metadata": {}, "outputs": [], "source": [] diff --git a/fastplotlib/graphics/heatmap.py b/fastplotlib/graphics/heatmap.py index 4eb9950a2..b4e29e902 100644 --- a/fastplotlib/graphics/heatmap.py +++ b/fastplotlib/graphics/heatmap.py @@ -46,6 +46,7 @@ def __init__( class HeatmapGraphic(ImageGraphic, Interaction): + @property def indices(self) -> Any: pass @@ -54,11 +55,10 @@ def indices(self) -> Any: def features(self) -> List[str]: pass - def _set_feature(self, name: str, new_data: Any, indices: Any): + def _set_feature(self, feature: str, new_data: Any, indices: Any): pass - def link(self, event: str, feature: Any, feature_data: Any, target: Graphic, target_feature: Any, target_data: Any, - indices_mapper: Any): + def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): pass def __init__( diff --git a/fastplotlib/graphics/image.py b/fastplotlib/graphics/image.py index c184d1c66..0c9454f78 100644 --- a/fastplotlib/graphics/image.py +++ b/fastplotlib/graphics/image.py @@ -1,13 +1,13 @@ -from typing import Tuple +from typing import Tuple, Any, List import numpy as np import pygfx -from ._base import Graphic +from ._base import Graphic, Interaction from ..utils import quick_min_max, get_cmap_texture -class ImageGraphic(Graphic): +class ImageGraphic(Graphic, Interaction): def __init__( self, data: np.ndarray, @@ -30,6 +30,20 @@ def __init__( pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=get_cmap_texture(cmap)) ) + @property + def indices(self) -> Any: + pass + + @property + def features(self) -> List[str]: + pass + + def _set_feature(self, feature: str, new_data: Any, indices: Any): + pass + + def _reset_feature(self): + pass + @property def clim(self) -> Tuple[float, float]: return self.world_object.material.clim diff --git a/fastplotlib/graphics/linecollection.py b/fastplotlib/graphics/linecollection.py index 7d05b8e1d..ebd111fc3 100644 --- a/fastplotlib/graphics/linecollection.py +++ b/fastplotlib/graphics/linecollection.py @@ -2,12 +2,12 @@ import pygfx from typing import Union, List -from fastplotlib.graphics._base import Graphic - from .line import LineGraphic from typing import * from ._base import Interaction +from abc import ABC, abstractmethod + class LineCollection(Interaction): def __init__(self, data: List[np.ndarray], zlevel: Union[List[float], float] = None, size: Union[float, List[float]] = 2.0, colors: Union[List[np.ndarray], np.ndarray] = None, @@ -51,19 +51,28 @@ def __init__(self, data: List[np.ndarray], zlevel: Union[List[float], float] = N self.collection.append(LineGraphic(d, _zlevel, _size, _colors, _cmap)) + def _reset_feature(self): + pass + @property def indices(self) -> Any: pass + @indices.setter + @abstractmethod + def indices(self, indices: Any): + pass + @property def features(self) -> List[str]: pass def _set_feature(self, feature: str, new_data: Any, indices: Any): - pass - - def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): - pass + if feature in ["colors", "data"]: + update_func = getattr(self, f"update_{feature}") + self.collection[indices].update_func(new_data) + else: + raise ValueError("name arg is not a valid feature") def __getitem__(self, item): return self.collection[item] From b3767ff963be25246e126bdcb72c2174f0649ffb Mon Sep 17 00:00:00 2001 From: Caitlin Lewis <69729525+clewis7@users.noreply.github.com> Date: Mon, 19 Dec 2022 12:19:59 -0500 Subject: [PATCH 14/19] Delete event_handler.ipynb --- examples/event_handler.ipynb | 426 ----------------------------------- 1 file changed, 426 deletions(-) delete mode 100644 examples/event_handler.ipynb diff --git a/examples/event_handler.ipynb b/examples/event_handler.ipynb deleted file mode 100644 index 9c22e77a9..000000000 --- a/examples/event_handler.ipynb +++ /dev/null @@ -1,426 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "a0b458c1-53c6-43d9-a72a-41f51bfe493d", - "metadata": {}, - "source": [ - "### notebook for learning event handler system" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "638b6a65-6d78-459c-ac88-35312233d22a", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2022-12-19 11:35:14.246180: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", - "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", - "2022-12-19 11:35:14.498269: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", - "2022-12-19 11:35:14.542615: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-19 11:35:14.542629: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", - "2022-12-19 11:35:15.350591: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-19 11:35:15.350720: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-19 11:35:15.350726: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" - ] - }, - { - "ename": "ImportError", - "evalue": "cannot import name 'Graphic' from partially initialized module 'fastplotlib.graphics._base' (most likely due to a circular import) (/home/caitlin/repos/fastplotlib/fastplotlib/graphics/_base.py)", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[1], line 5\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mmatplotlib\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m pyplot \u001b[38;5;28;01mas\u001b[39;00m plt\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpandas\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mpd\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfastplotlib\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m GridPlot, Image, Plot, Line, Heatmap\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mscipy\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mspatial\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m distance\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mipywidgets\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mwidgets\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m IntSlider, VBox\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Plot\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpathlib\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Path\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mwgpu\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgui\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mauto\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m run\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/plot.py:3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mwgpu\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgui\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mauto\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WgpuCanvas\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlayouts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_subplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Subplot\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m graphics\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfunctools\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m partial\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/layouts/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_gridplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m GridPlot\n\u001b[1;32m 3\u001b[0m __all__ \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 4\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGridPlot\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 5\u001b[0m ]\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/layouts/_gridplot.py:5\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_defaults\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m create_controller\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_subplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Subplot\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;241m*\u001b[39m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mwgpu\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgui\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mauto\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WgpuCanvas\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/layouts/_subplot.py:3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Scene, OrthographicCamera, PanZoomController, OrbitOrthoController, \\\n\u001b[1;32m 2\u001b[0m AxesHelper, GridHelper, WgpuRenderer, Background, BackgroundMaterial\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgraphics\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m HeatmapGraphic\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_defaults\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m create_camera, create_controller\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;241m*\u001b[39m\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mhistogram\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m HistogramGraphic\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mline\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LineGraphic\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mscatter\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ScatterGraphic\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/histogram.py:7\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mnumpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnp\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[0;32m----> 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_base\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Graphic\n\u001b[1;32m 10\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01m_HistogramBin\u001b[39;00m(pygfx\u001b[38;5;241m.\u001b[39mMesh):\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__int__\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/_base.py:10\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mabc\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ABC, abstractmethod\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mdataclasses\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m dataclass\n\u001b[0;32m---> 10\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlinecollection\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LineCollection\n\u001b[1;32m 12\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mGraphic\u001b[39;00m:\n\u001b[1;32m 13\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 15\u001b[0m data,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 20\u001b[0m name: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 21\u001b[0m ):\n", - "File \u001b[0;32m~/repos/fastplotlib/fastplotlib/graphics/linecollection.py:5\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpygfx\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Union, List\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mfastplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgraphics\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_base\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Graphic\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mline\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LineGraphic\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;241m*\u001b[39m\n", - "\u001b[0;31mImportError\u001b[0m: cannot import name 'Graphic' from partially initialized module 'fastplotlib.graphics._base' (most likely due to a circular import) (/home/caitlin/repos/fastplotlib/fastplotlib/graphics/_base.py)" - ] - } - ], - "source": [ - "from mesmerize_core import *\n", - "import numpy as np\n", - "from matplotlib import pyplot as plt\n", - "import pandas as pd\n", - "from fastplotlib import GridPlot, Image, Plot, Line, Heatmap\n", - "from scipy.spatial import distance\n", - "from ipywidgets.widgets import IntSlider, VBox\n", - "import pygfx" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "80938adc-1775-4751-94dd-89fb94ed673a", - "metadata": {}, - "outputs": [], - "source": [ - "class Contour_Selection():\n", - " def __init__(\n", - " self,\n", - " gp: GridPlot,\n", - " coms,\n", - " ):\n", - " self.gp = gp\n", - " self.heatmap = self.gp.subplots[0, 1].scene.children[0]\n", - " self.image = None\n", - " self._contour_index = None \n", - " \n", - " for child in self.gp.subplots[0, 0].scene.children:\n", - " if isinstance(child, pygfx.Image):\n", - " self.image = child\n", - " break;\n", - " if self.image == None:\n", - " raise ValueError(\"No image found!\")\n", - " self.coms = np.array(coms)\n", - " \n", - " self.image.add_event_handler(self.event_handler, \"click\")\n", - " \n", - " # first need to add event handler for when contour is clicked on\n", - " # should also trigger highlighting in heatmap\n", - " def event_handler(self, event):\n", - " if self._contour_index is not None:\n", - " self.remove_highlight()\n", - " self.add_highlight(event)\n", - " else:\n", - " self.add_highlight(event)\n", - " \n", - " def add_highlight(self, event):\n", - " click_location = np.array(event.pick_info[\"index\"])\n", - " self._contour_index = np.linalg.norm((self.coms - click_location), axis=1).argsort()[0] + 1\n", - " line = self.gp.subplots[0, 0].scene.children[self._contour_index]\n", - " line.geometry.colors.data[:] = np.array([1.0, 1.0, 1.0, 1.0]) \n", - " line.geometry.colors.update_range()\n", - " #self.heatmap.add_highlight(self._contour_index)\n", - " \n", - " def remove_highlight(self):\n", - " # change color of highlighted index back to normal\n", - " line = self.gp.subplots[0, 0].scene.children[self._contour_index]\n", - " line.geometry.colors.data[:] = np.array([1., 0., 0., 0.7]) \n", - " line.geometry.colors.update_range()\n", - " # for h in self.heatmap._highlights:\n", - " # self.heatmap.remove_highlight(h)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "7b3129e6-5d82-4f39-b887-e584421c3a74", - "metadata": {}, - "outputs": [], - "source": [ - "set_parent_raw_data_path(\"/home/kushal/caiman_data/\")\n", - "\n", - "batch_path = \"/home/clewis7/caiman_data/cnmf_practice/batch.pickle\"\n", - "\n", - "movie_path = \"/home/kushal/caiman_data/example_movies/Sue_2x_3000_40_-46.tif\"" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "776c6dd8-cf07-47ee-bcc4-5fe84bc030f5", - "metadata": {}, - "outputs": [], - "source": [ - "df = load_batch(batch_path)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "b22fd79b-5a7a-48fb-898c-4d3f3a34c118", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
algoitem_nameinput_movie_pathparamsoutputscommentsuuid
0mcorrmy_movieexample_movies/Sue_2x_3000_40_-46.tif{'main': {'max_shifts': (24, 24), 'strides': (...{'mean-projection-path': 1ed8feb3-9fc8-4a78-8f...None1ed8feb3-9fc8-4a78-8f6d-164620822016
1cnmfmy_movie1ed8feb3-9fc8-4a78-8f6d-164620822016/1ed8feb3-...{'main': {'fr': 30, 'p': 1, 'nb': 2, 'merge_th...{'mean-projection-path': 5f4e3e27-ac1f-4ede-90...None5f4e3e27-ac1f-4ede-903b-be43bd81fddc
\n", - "
" - ], - "text/plain": [ - " algo item_name input_movie_path \\\n", - "0 mcorr my_movie example_movies/Sue_2x_3000_40_-46.tif \n", - "1 cnmf my_movie 1ed8feb3-9fc8-4a78-8f6d-164620822016/1ed8feb3-... \n", - "\n", - " params \\\n", - "0 {'main': {'max_shifts': (24, 24), 'strides': (... \n", - "1 {'main': {'fr': 30, 'p': 1, 'nb': 2, 'merge_th... \n", - "\n", - " outputs comments \\\n", - "0 {'mean-projection-path': 1ed8feb3-9fc8-4a78-8f... None \n", - "1 {'mean-projection-path': 5f4e3e27-ac1f-4ede-90... None \n", - "\n", - " uuid \n", - "0 1ed8feb3-9fc8-4a78-8f6d-164620822016 \n", - "1 5f4e3e27-ac1f-4ede-903b-be43bd81fddc " - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "03045957-837e-49e3-83aa-3e069af977a1", - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3b283ef0f3084d828f80fd3a6cb25413", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "8b104ac5f10e4d53866953a4401593df", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(JupyterWgpuCanvas(), IntSlider(value=0, max=2999)))" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "gp = GridPlot(shape=(1,2))\n", - "\n", - "contours, coms = df.iloc[-1].cnmf.get_contours()\n", - "movie = df.iloc[-1].cnmf.get_input_memmap()\n", - "temporal = df.iloc[-1].cnmf.get_temporal()\n", - "\n", - "contour_graphic = Image(movie[0].T, cmap=\"gnuplot2\")\n", - "heatmap = Heatmap(data=temporal[:,0:1000], cmap=\"jet\")\n", - "\n", - "slider = IntSlider(value=0, min=0, max=movie.shape[0] - 1, step=1)\n", - "\n", - "gp.subplots[0,0].add_graphic(contour_graphic)\n", - "gp.subplots[0,1].add_graphic(heatmap)\n", - "\n", - "for coor in contours:\n", - " # line data has to be 3D\n", - " zs = np.ones(coor.shape[0]) # this will place it above the image graphic\n", - " c3d = [coor[:, 0], coor[:, 1], zs]\n", - " coors_3d = np.dstack(c3d)[0]\n", - "\n", - " # make all the lines red, [R, G, B, A] array\n", - " colors = np.vstack([[1., 0., 0., 0.7]] * coors_3d.shape[0])\n", - " line_graphic = Line(data=coors_3d, colors=colors, zlevel=1)\n", - " gp.subplots[0, 0].add_graphic(line_graphic)\n", - "\n", - "previous_slider_value = 0\n", - "def update_frame(): \n", - " if slider.value == previous_slider_value:\n", - " return\n", - " contour_graphic.update_data(data=movie[slider.value].T)\n", - "\n", - "gp.add_animations([update_frame])\n", - "\n", - "VBox([gp.show(), slider])" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "2bf4a1ea-3559-4846-bc32-4dddaca2d470", - "metadata": {}, - "outputs": [], - "source": [ - "contour_selection = Contour_Selection(gp=gp, coms=coms)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "5ecdbdea-4e77-462f-a18d-5ed9b45faada", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(155, 3000)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "temporal.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "51b3feea-af91-4158-97a2-8dbadd2480b5", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "numpy.ndarray" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "type(coms[0])" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "3b2011f4-046b-4396-a592-81a5128d2482", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([7.12861818, 9.84114483])" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "coms[0]" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "c5791bf4-a116-4093-bce1-eee7bc25221c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gp.subplots[0, 1]" - ] - }, - { - "cell_type": "markdown", - "id": "ae9cce16-370f-44d2-b532-dc442cce379d", - "metadata": {}, - "source": [ - "next steps:\n", - " clicking on a contour should highlight it and the heatmap row" - ] - } - ], - "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.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 462f098ee7dd13c874b4a5762033c86fb35d6576 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis <69729525+clewis7@users.noreply.github.com> Date: Mon, 19 Dec 2022 12:20:10 -0500 Subject: [PATCH 15/19] Delete event_linecollection.ipynb --- examples/event_linecollection.ipynb | 455 ---------------------------- 1 file changed, 455 deletions(-) delete mode 100644 examples/event_linecollection.ipynb diff --git a/examples/event_linecollection.ipynb b/examples/event_linecollection.ipynb deleted file mode 100644 index ff23b623c..000000000 --- a/examples/event_linecollection.ipynb +++ /dev/null @@ -1,455 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9cba8fd1-5bd6-431b-a0d8-4fc671bbc631", - "metadata": {}, - "source": [ - "# working on interactivity for linecollection" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "f5d95c3d-1260-4dd9-81de-e29356022046", - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "5733cb62-f688-450b-aa20-3fd1e994d729", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2022-12-18 14:41:24.532552: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", - "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", - "2022-12-18 14:41:24.625689: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", - "2022-12-18 14:41:24.628296: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-18 14:41:24.628306: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", - "2022-12-18 14:41:25.058487: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-18 14:41:25.058533: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-18 14:41:25.058537: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" - ] - } - ], - "source": [ - "import numpy as np\n", - "from fastplotlib.plot import Plot\n", - "from fastplotlib.graphics import LineGraphic, LineCollection, ImageGraphic\n", - "import pygfx\n", - "import pickle\n", - "from mesmerize_core import *\n", - "import tifffile" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "840d59ca-f3a6-4a32-8393-a1250ed40121", - "metadata": {}, - "outputs": [], - "source": [ - "contours = pickle.load(open(\"/home/caitlin/Downloads/contours.pickle\", \"rb\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "1e769837-639e-4da8-953c-4b312a1096cb", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "155" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(contours)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "2f095853-3304-42d8-970e-c01db8cf8152", - "metadata": {}, - "outputs": [], - "source": [ - "line_collection = LineCollection(data=contours, size=5.0, cmap=\"jet\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "b6dcf23c-21aa-46cb-8749-7fb298f2ace5", - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c7bc183cce3a45c281d9868f3e055b3a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "MESA-INTEL: warning: Performance support disabled, consider sysctl dev.i915.perf_stream_paranoid=0\n", - "\n" - ] - } - ], - "source": [ - "plot = Plot()" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "ed02c2f0-58f3-4e57-91b8-7f5b03759e97", - "metadata": {}, - "outputs": [], - "source": [ - "# create image to use for linking \n", - "data = np.ones((190, 200))\n", - "img = ImageGraphic(data=data)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "64404ac7-e33a-4bef-bae7-31488a730c39", - "metadata": {}, - "outputs": [], - "source": [ - "# add image first and use for handling image\n", - "for contour in line_collection:\n", - " plot.add_graphic(contour)\n", - "plot.add_graphic(img)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "921e0b11-de3d-4a0f-8035-3c1f1c562a5e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "9da3b15ceb03437e84d665975ca1c119", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "plot.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "ccbf3a5b-f35e-4017-a751-404e0168e8e6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([10. , 10.0773941])" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "contours[0][0]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8617453b-435b-4362-bd9e-6041f0004312", - "metadata": {}, - "outputs": [], - "source": [ - "coordinates = list()\n", - "coms = list()\n", - "\n", - "for contour in contours:\n", - " for coor in contour:\n", - " coor = coor[~np.isnan(coors).any(axis=1)]\n", - " coordinates.append(coor)\n", - "\n", - " com = coors.mean(axis=0)\n", - " coms.append(com)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b812c149-3c7a-41a8-922e-6bf133788066", - "metadata": {}, - "outputs": [], - "source": [ - "click_location = np.array(event.pick_info[\"index\"])\n", - "self._contour_index = np.linalg.norm((self.coms - click_location), axis=1).argsort()[0] + 1\n", - "\n", - "def indices_mapper(click_location: np.array, coms: List) -> int:\n", - " # should take in some params and then return the index of the contour that needs to be changed, color or data\n", - " # needs to take in the data of all the contours\n", - " # calculates the coms\n", - " # euclidean distance from pick info find the index \n", - " # return the index" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "037582e9-6bc1-474a-badc-126054abc82a", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[fastplotlib.LineGraphic @ 0x7f59c5ff18e0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ff1cd0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ff1ca0,\n", - " fastplotlib.LineGraphic @ 0x7f59c6000b80,\n", - " fastplotlib.LineGraphic @ 0x7f59c600a340,\n", - " fastplotlib.LineGraphic @ 0x7f59c600ab20,\n", - " fastplotlib.LineGraphic @ 0x7f59c6013340,\n", - " fastplotlib.LineGraphic @ 0x7f59c6013b20,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f9c340,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f9cb20,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fa5340,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fa5b20,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fae340,\n", - " fastplotlib.LineGraphic @ 0x7f59c5faed00,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fb9790,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fbe220,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fbec70,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fc6700,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fce190,\n", - " fastplotlib.LineGraphic @ 0x7f59c5fcebe0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f55670,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f5d100,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f5db50,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f655e0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f6b070,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f6bac0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f73550,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f73fa0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f7ba30,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f834c0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f83f10,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f8c9a0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f94430,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f94e80,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f1a910,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f233a0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f23df0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f2b880,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f31310,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f31dc0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f38850,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f422e0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f42d30,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f4b7c0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f50250,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f50ca0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ed9730,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ede1c0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5edec10,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ee96a0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ef1130,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ef1b80,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ef7610,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f010a0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f01af0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f06580,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f06fd0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5f10a60,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e964f0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e96f40,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e9e9d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ea8460,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ea8eb0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5eae940,\n", - " fastplotlib.LineGraphic @ 0x7f59c5eb73d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5eb7e20,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ebe8b0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ec5340,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ec5d90,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ece820,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e562b0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e56d00,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e5d790,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e64220,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e64c70,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e6c700,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e75190,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e75be0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e7b670,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e83100,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e83b50,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e8d5e0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e94070,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e94ac0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e1b550,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e1bfa0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e21a30,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e2c4c0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e2cf10,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e339a0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e3b430,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e3be80,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e41910,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e4a3a0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e4adf0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e51880,\n", - " fastplotlib.LineGraphic @ 0x7f59c5dda310,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ddad60,\n", - " fastplotlib.LineGraphic @ 0x7f59c5de37f0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5de8280,\n", - " fastplotlib.LineGraphic @ 0x7f59c5de8cd0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5df1760,\n", - " fastplotlib.LineGraphic @ 0x7f59c5df71f0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5df7c40,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e006d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e09160,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e09bb0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5e10640,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d990d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d99b20,\n", - " fastplotlib.LineGraphic @ 0x7f59c5da05b0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5da7040,\n", - " fastplotlib.LineGraphic @ 0x7f59c5da7a90,\n", - " fastplotlib.LineGraphic @ 0x7f59c5daf520,\n", - " fastplotlib.LineGraphic @ 0x7f59c5daff70,\n", - " fastplotlib.LineGraphic @ 0x7f59c5db6a00,\n", - " fastplotlib.LineGraphic @ 0x7f59c5dbf490,\n", - " fastplotlib.LineGraphic @ 0x7f59c5dbfee0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5dc6970,\n", - " fastplotlib.LineGraphic @ 0x7f59c5dcf400,\n", - " fastplotlib.LineGraphic @ 0x7f59c5dcfe50,\n", - " fastplotlib.LineGraphic @ 0x7f59c5dd48e0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d5e370,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d5edc0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d66850,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d6c2e0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d6cd30,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d777c0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d7b280,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d7bcd0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d86760,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d8c1f0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d8cc40,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d166d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d1e160,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d1ebb0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d25640,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d2b0d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d2bb20,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d345b0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d3b070,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d3bac0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d45580,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d45fd0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d4ca60,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d534f0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d53f40,\n", - " fastplotlib.LineGraphic @ 0x7f59c5cdb9d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ce4460,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ce4eb0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5ceb940,\n", - " fastplotlib.LineGraphic @ 0x7f59c5cf13d0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5cf1e20,\n", - " fastplotlib.LineGraphic @ 0x7f59c5cfa8b0,\n", - " fastplotlib.LineGraphic @ 0x7f59c5d03340,\n", - " fastplotlib.ImageGraphic @ 0x7f5a5002d5b0]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# link image\n", - "img.link(event_type=\"click\", target=line_collection, feature=\"colors\", indices_mapper=indices_mapper)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f3659f8b-031c-475e-b265-7ebeebe858c9", - "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.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 70997830f24576adb51fe9a9a5398b9e2c64e988 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis <69729525+clewis7@users.noreply.github.com> Date: Mon, 19 Dec 2022 12:20:20 -0500 Subject: [PATCH 16/19] Delete event_single_contour.ipynb --- examples/event_single_contour.ipynb | 368 ---------------------------- 1 file changed, 368 deletions(-) delete mode 100644 examples/event_single_contour.ipynb diff --git a/examples/event_single_contour.ipynb b/examples/event_single_contour.ipynb deleted file mode 100644 index 1174b040d..000000000 --- a/examples/event_single_contour.ipynb +++ /dev/null @@ -1,368 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "2d14adc9-1ba0-4a5c-ab7d-d31d5fad238d", - "metadata": {}, - "source": [ - "# working on event interactivity for a single contour" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "a934868b-3792-48da-83e7-793350545a09", - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "4420c0dc-23f9-4405-bc0b-b2b745061326", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2022-12-19 12:04:42.299047: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", - "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", - "2022-12-19 12:04:42.399624: I tensorflow/core/util/port.cc:104] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", - "2022-12-19 12:04:42.402140: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-19 12:04:42.402151: I tensorflow/compiler/xla/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", - "2022-12-19 12:04:42.835552: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-19 12:04:42.835614: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /home/caitlin/venvs/mescore/lib/python3.9/site-packages/cv2/../../lib64:\n", - "2022-12-19 12:04:42.835619: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n" - ] - } - ], - "source": [ - "import numpy as np\n", - "from fastplotlib.plot import Plot\n", - "from fastplotlib.graphics import LineGraphic\n", - "import pygfx\n", - "import pickle\n", - "from mesmerize_core import *\n", - "import tifffile" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "3eb77356-5314-4004-ac26-0628a19c038b", - "metadata": {}, - "outputs": [], - "source": [ - "contours = pickle.load(open(\"/home/caitlin/Downloads/contours.pickle\", \"rb\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "0b2090b9-9fe6-407e-b517-2b8b28d38d2e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "155" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(contours)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "90373974-c3a1-468e-8cf2-8c31061284a6", - "metadata": {}, - "outputs": [], - "source": [ - "single_contour = LineGraphic(data=contours[0], size=10.0, cmap=\"jet\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "a8e24de1-a3a7-4f6d-bdd8-b32f91a138e4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0. , 0. , 0.5 , 1. ],\n", - " [0. , 0. , 0.6604278 , 1. ],\n", - " [0. , 0. , 0.8386809 , 1. ],\n", - " [0. , 0. , 1. , 1. ],\n", - " [0. , 0.11176471, 1. , 1. ],\n", - " [0. , 0.26862746, 1. , 1. ],\n", - " [0. , 0.40980393, 1. , 1. ],\n", - " [0. , 0.56666666, 1. , 1. ],\n", - " [0. , 0.7235294 , 1. , 1. ],\n", - " [0. , 0.88039213, 0.9835547 , 1. ],\n", - " [0.11068944, 1. , 0.8570525 , 1. ],\n", - " [0.22454143, 1. , 0.7432005 , 1. ],\n", - " [0.35104364, 1. , 0.61669827, 1. ],\n", - " [0.47754586, 1. , 0.49019608, 1. ],\n", - " [0.6040481 , 1. , 0.36369386, 1. ],\n", - " [0.7305503 , 1. , 0.23719165, 1. ],\n", - " [0.84440225, 1. , 0.12333966, 1. ],\n", - " [0.97090447, 0.95933187, 0. , 1. ],\n", - " [1. , 0.8140886 , 0. , 1. ],\n", - " [1. , 0.6688453 , 0. , 1. ],\n", - " [1. , 0.523602 , 0. , 1. ],\n", - " [1. , 0.3928831 , 0. , 1. ],\n", - " [1. , 0.24763979, 0. , 1. ],\n", - " [1. , 0.10239651, 0. , 1. ],\n", - " [0.8565062 , 0. , 0. , 1. ],\n", - " [0.6782531 , 0. , 0. , 1. ],\n", - " [0.5 , 0. , 0. , 1. ]], dtype=float32)" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "single_contour.colors" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "ae0adaec-be96-4fe7-8aa5-07b3bb6b7c18", - "metadata": {}, - "outputs": [], - "source": [ - "feature = \"colors\"" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "30cfdbd9-0cc1-4aa2-81e4-c009e8f483ad", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0. , 0. , 0.5 , 1. ],\n", - " [0. , 0. , 0.6604278 , 1. ],\n", - " [0. , 0. , 0.8386809 , 1. ],\n", - " [0. , 0. , 1. , 1. ],\n", - " [0. , 0.11176471, 1. , 1. ],\n", - " [0. , 0.26862746, 1. , 1. ],\n", - " [0. , 0.40980393, 1. , 1. ],\n", - " [0. , 0.56666666, 1. , 1. ],\n", - " [0. , 0.7235294 , 1. , 1. ],\n", - " [0. , 0.88039213, 0.9835547 , 1. ],\n", - " [0.11068944, 1. , 0.8570525 , 1. ],\n", - " [0.22454143, 1. , 0.7432005 , 1. ],\n", - " [0.35104364, 1. , 0.61669827, 1. ],\n", - " [0.47754586, 1. , 0.49019608, 1. ],\n", - " [0.6040481 , 1. , 0.36369386, 1. ],\n", - " [0.7305503 , 1. , 0.23719165, 1. ],\n", - " [0.84440225, 1. , 0.12333966, 1. ],\n", - " [0.97090447, 0.95933187, 0. , 1. ],\n", - " [1. , 0.8140886 , 0. , 1. ],\n", - " [1. , 0.6688453 , 0. , 1. ],\n", - " [1. , 0.523602 , 0. , 1. ],\n", - " [1. , 0.3928831 , 0. , 1. ],\n", - " [1. , 0.24763979, 0. , 1. ],\n", - " [1. , 0.10239651, 0. , 1. ],\n", - " [0.8565062 , 0. , 0. , 1. ],\n", - " [0.6782531 , 0. , 0. , 1. ],\n", - " [0.5 , 0. , 0. , 1. ]], dtype=float32)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "getattr(single_contour, feature)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "ba7765c1-5c2f-4898-a250-9894b11153c4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{}" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "single_contour.registered_callbacks" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "df16cf45-a767-40ce-a1f5-efac891b57f5", - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "30efba9281ef4564a58a3b2a3cbcac73", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "MESA-INTEL: warning: Performance support disabled, consider sysctl dev.i915.perf_stream_paranoid=0\n", - "\n" - ] - } - ], - "source": [ - "plot = Plot()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "038eb7d8-f4cf-4d0e-8aa5-1e52c65d0fe3", - "metadata": {}, - "outputs": [], - "source": [ - "plot.add_graphic(single_contour)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "c6ffada3-4b52-4a54-815e-d07581240433", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "43085a939e61460395b69e5a19242f6d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "plot.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "73ab4a53-f26b-4668-8603-eba027449d82", - "metadata": {}, - "outputs": [], - "source": [ - "white = np.ones(shape=single_contour.colors.shape)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "3803b5d4-0c1e-4b0d-803c-7bb769a310d2", - "metadata": {}, - "outputs": [], - "source": [ - "single_contour.link(event_type=\"click\", target=single_contour, feature=\"colors\", new_data=white)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6e5cd5e4-da0b-465c-b46a-d6bd9b54f36d", - "metadata": {}, - "outputs": [], - "source": [ - "single_contour.registered_callbacks" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "39c2362a-3fc7-49c7-8623-a5720720678c", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "42008ad7-cd12-4756-adb2-92cccafffda0", - "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.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From c523c283fd68567dc771e78b90337b8907b3c05a Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Mon, 19 Dec 2022 12:22:16 -0500 Subject: [PATCH 17/19] accidentally deleted heatmap file --- fastplotlib/graphics/heatmap.py | 137 ++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 fastplotlib/graphics/heatmap.py diff --git a/fastplotlib/graphics/heatmap.py b/fastplotlib/graphics/heatmap.py new file mode 100644 index 000000000..103a0fc2e --- /dev/null +++ b/fastplotlib/graphics/heatmap.py @@ -0,0 +1,137 @@ +import numpy as np +import pygfx +from typing import * +from .image import ImageGraphic + +from ..utils import quick_min_max, get_cmap_texture + + +default_selection_options = { + "mode": "single", + "orientation": "row", + "callbacks": None, +} + + +class SelectionOptions: + def __init__( + self, + event: str = "double_click", # click or double_click + event_button: Union[int, str] = 1, + mode: str = "single", + axis: str = "row", + color: Tuple[int, int, int, int] = None, + callbacks: List[callable] = None, + ): + self.event = event + self.event_button = event_button + self.mode = mode + self.axis = axis + + if color is not None: + self.color = color + + else: + self.color = (1, 1, 1, 0.4) + + if callbacks is None: + self.callbacks = list() + else: + self.callbacks = callbacks + + +class HeatmapGraphic(ImageGraphic): + def __init__( + self, + data: np.ndarray, + vmin: int = None, + vmax: int = None, + cmap: str = 'plasma', + selection_options: dict = None, + *args, + **kwargs + ): + """ + Create a Heatmap Graphic + Parameters + ---------- + data: array-like, must be 2-dimensional + | array-like, usually numpy.ndarray, must support ``memoryview()`` + | Tensorflow Tensors also work _I think_, but not thoroughly tested + vmin: int, optional + minimum value for color scaling, calculated from data if not provided + vmax: int, optional + maximum value for color scaling, calculated from data if not provided + cmap: str, optional + colormap to use to display the image data, default is ``"plasma"`` + selection_options + args: + additional arguments passed to Graphic + kwargs: + additional keyword arguments passed to Graphic + """ + super().__init__(data, vmin, vmax, cmap, *args, **kwargs) + + self.selection_options = SelectionOptions() + self.selection_options.callbacks = list() + + if selection_options is not None: + for k in selection_options.keys(): + setattr(self.selection_options, k, selection_options[k]) + + self.world_object.add_event_handler( + self.handle_selection_event, self.selection_options.event + ) + + self._highlights = list() + + def handle_selection_event(self, event): + if not event.button == self.selection_options.event_button: + return + + if self.selection_options.mode == "single": + for h in self._highlights: + self.remove_highlight(h) + + rval = self.add_highlight(event) + + for f in self.selection_options.callbacks: + f(rval) + + def remove_highlight(self, h): + self._highlights.remove(h) + self.world_object.remove(h) + + def add_highlight(self, event): + index = event.pick_info["index"] + + if self.selection_options.axis == "row": + index = index[1] + w = self.data.shape[1] + h = 1 + + pos = ((self.data.shape[1] / 2) - 0.5, index, 1) + rval = self.data[index, :] # returned to selection.callbacks functions + + elif self.selection_options.axis == "column": + index = index[0] + w = 1 + h = self.data.shape[0] + + pos = (index, (self.data.shape[0] / 2) - 0.5, 1) + rval = self.data[:, index] + + geometry = pygfx.plane_geometry( + width=w, + height=h + ) + + material = pygfx.MeshBasicMaterial(color=self.selection_options.color) + + self.selection_graphic = pygfx.Mesh(geometry, material) + self.selection_graphic.position.set(*pos) + + self.world_object.add(self.selection_graphic) + self._highlights.append(self.selection_graphic) + + return rval \ No newline at end of file From 9309b415e45da2dd611e7b8ff0f32ea7dde8fa01 Mon Sep 17 00:00:00 2001 From: Caitlin Lewis Date: Tue, 20 Dec 2022 14:31:23 -0500 Subject: [PATCH 18/19] ugly but functional --- examples/linecollection_event.ipynb | 247 +++++++++++++++++++++++++ fastplotlib/graphics/__init__.py | 4 +- fastplotlib/graphics/_base.py | 40 ++-- fastplotlib/graphics/image.py | 12 +- fastplotlib/graphics/line.py | 12 +- fastplotlib/graphics/linecollection.py | 40 ++-- 6 files changed, 301 insertions(+), 54 deletions(-) create mode 100644 examples/linecollection_event.ipynb diff --git a/examples/linecollection_event.ipynb b/examples/linecollection_event.ipynb new file mode 100644 index 000000000..a74befd36 --- /dev/null +++ b/examples/linecollection_event.ipynb @@ -0,0 +1,247 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "0c32716f-320e-4021-ad60-1c142fe6fd56", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6d72f23c-0f3a-4b2c-806d-3b239237c725", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from fastplotlib.graphics import ImageGraphic, LineCollection\n", + "from fastplotlib.plot import Plot\n", + "import pickle" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2fb13990-63fc-4fc6-b5c1-93f8ec4c1572", + "metadata": {}, + "outputs": [], + "source": [ + "contours = pickle.load(open(\"/home/caitlin/Downloads/contours.pickle\", \"rb\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e7970865-913e-4a58-b2eb-d262e60866de", + "metadata": {}, + "outputs": [], + "source": [ + "line_collection = LineCollection(data=contours, cmap=\"jet\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "637d7c99-a1d6-49dc-9543-f14d49bc49ed", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8cf2ae1b21aa44d38a9814c044101394", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "RFBOutputContext()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "MESA-INTEL: warning: Performance support disabled, consider sysctl dev.i915.perf_stream_paranoid=0\n", + "\n" + ] + } + ], + "source": [ + "plot = Plot()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4d89370a-d099-4ca1-96cf-bb8c8909ae65", + "metadata": {}, + "outputs": [], + "source": [ + "data = np.ones(shape=(175, 175))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4d302b06-e384-4cd6-bc54-56184c65523e", + "metadata": {}, + "outputs": [], + "source": [ + "img = ImageGraphic(data=data)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "52228653-e030-44a1-affc-bad45d675ea7", + "metadata": {}, + "outputs": [], + "source": [ + "for contour in line_collection:\n", + " plot.add_graphic(contour)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "4cd10499-18c8-461a-a27b-b7d7ac1bc7ea", + "metadata": {}, + "outputs": [], + "source": [ + "plot.add_graphic(img)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "6698969b-5f4b-4b19-b03a-cca6cddd78c8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
initial snapshot
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3e521e3ccacc4c36921d51e75249de01", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "JupyterWgpuCanvas()" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "e321cf0d-52f7-4da2-983a-ff10653093bb", + "metadata": {}, + "outputs": [], + "source": [ + "white = list()\n", + "for contour in line_collection:\n", + " white.append(np.ones(shape=contour.colors.shape))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "4430e805-54db-4218-967a-30290ced8ca9", + "metadata": {}, + "outputs": [], + "source": [ + "from typing import *" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "c02210db-5347-4e97-a551-f4f362d3910a", + "metadata": {}, + "outputs": [], + "source": [ + "def indices_mapper(target: Any, indices: np.array) -> int:\n", + " # calculate coms of line collection \n", + " \n", + " coms = list()\n", + "\n", + " for contour in target.data:\n", + " coors = contour.data[~np.isnan(contour.data).any(axis=1)]\n", + " com = coors.mean(axis=0)\n", + " coms.append(com)\n", + "\n", + " # euclidean distance to find closest index of com \n", + " indices = np.append(indices, [0])\n", + " \n", + " ix = np.linalg.norm((coms - indices), axis=1).argsort()[0] \n", + " \n", + " #return that index to set feature \n", + " return ix" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "763dc328-c47b-4240-a0e9-792c0e8b1240", + "metadata": {}, + "outputs": [], + "source": [ + "img.link(event_type=\"click\", target=line_collection, feature=\"colors\", new_data=white, indices_mapper=indices_mapper)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00f6039c-230f-4b90-a448-071e899d976d", + "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.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/fastplotlib/graphics/__init__.py b/fastplotlib/graphics/__init__.py index cad6de8c7..6294637aa 100644 --- a/fastplotlib/graphics/__init__.py +++ b/fastplotlib/graphics/__init__.py @@ -12,6 +12,6 @@ "LineGraphic", "HistogramGraphic", "HeatmapGraphic", - "LineCollection", - "TextGraphic" + "TextGraphic", + "LineCollection" ] diff --git a/fastplotlib/graphics/_base.py b/fastplotlib/graphics/_base.py index 8d2942816..f9f7f08c2 100644 --- a/fastplotlib/graphics/_base.py +++ b/fastplotlib/graphics/_base.py @@ -7,7 +7,6 @@ from abc import ABC, abstractmethod from dataclasses import dataclass -# from .linecollection import LineCollection class Graphic: def __init__( @@ -74,14 +73,12 @@ def __repr__(self): class Interaction(ABC): @property - @abstractmethod def indices(self) -> Any: - pass + return self.indices @indices.setter - @abstractmethod def indices(self, indices: Any): - pass + self.indices = indices @property @abstractmethod @@ -93,34 +90,53 @@ def _set_feature(self, feature: str, new_data: Any, indices: Any): pass @abstractmethod - def _reset_feature(self, feature: str, old_data: Any, indices: Any): + def _reset_feature(self, feature: str, old_data: Any): pass - def link(self, event_type: str, target: Graphic, feature: str, new_data: Any, indices_mapper: callable = None): + def link(self, event_type: str, target: Any, feature: str, new_data: Any, indices_mapper: callable = None): valid_events = ["click"] if event_type in valid_events: self.world_object.add_event_handler(self.event_handler, event_type) else: raise ValueError("event not possible") + if isinstance(target.data, List): + old_data = list() + for line in target.data: + old_data.append(getattr(line, feature).copy()) + else: + old_data = getattr(target, feature).copy() + if event_type in self.registered_callbacks.keys(): self.registered_callbacks[event_type].append( - CallbackData(target=target, feature=feature, new_data=new_data, old_data=getattr(target, feature).copy())) + CallbackData(target=target, feature=feature, new_data=new_data, old_data=old_data, indices_mapper=indices_mapper)) else: self.registered_callbacks[event_type] = list() self.registered_callbacks[event_type].append( - CallbackData(target=target, feature=feature, new_data=new_data, old_data=getattr(target, feature).copy())) + CallbackData(target=target, feature=feature, new_data=new_data, old_data=old_data, indices_mapper=indices_mapper)) def event_handler(self, event): + if event.type == "click": + # storing click information for each click in self.indices + #self.indices(np.array(event.pick_info["index"])) + click_info = np.array(event.pick_info["index"]) if event.type in self.registered_callbacks.keys(): for target_info in self.registered_callbacks[event.type]: - target_info.target._reset_feature(feature=target_info.feature, old_data=target_info.old_data, indices=None) - target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data, indices=None) + # need to map the indices to the target using indices_mapper + if target_info.indices_mapper is not None: + indices = target_info.indices_mapper(target=target_info.target, indices=click_info) + else: + indices = None + # reset feature of target using stored old data + target_info.target._reset_feature(feature=target_info.feature, old_data=target_info.old_data) + # set feature of target at indice using new data + target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data[indices], indices=indices) @dataclass class CallbackData: """Class for keeping track of the info necessary for interactivity after event occurs.""" - target: Graphic + target: Any feature: str new_data: Any old_data: Any + indices_mapper: callable = None diff --git a/fastplotlib/graphics/image.py b/fastplotlib/graphics/image.py index 29fe37fd7..efb18a93e 100644 --- a/fastplotlib/graphics/image.py +++ b/fastplotlib/graphics/image.py @@ -1,8 +1,4 @@ -<<<<<<< HEAD -from typing import Tuple, Any, List -======= from typing import * ->>>>>>> a9990946faa8b990ee2f5ab0f2fff93d99f18d9e import numpy as np import pygfx @@ -76,18 +72,14 @@ def __init__( pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=get_cmap_texture(cmap)) ) - @property - def indices(self) -> Any: - pass - @property def features(self) -> List[str]: - pass + return ["cmap", "data"] def _set_feature(self, feature: str, new_data: Any, indices: Any): pass - def _reset_feature(self): + def _reset_feature(self, feature: str, old_data: Any): pass @property diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index c84893af1..dbdef4ea2 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -56,23 +56,19 @@ def update_colors(self, colors: np.ndarray): self.world_object.geometry.colors.data[:] = self.colors self.world_object.geometry.colors.update_range() - @property - def indices(self) -> Any: - return None - @property def features(self) -> List[str]: - return None + return ["colors", "data"] def _set_feature(self, feature: str, new_data: Any, indices: Any = None): - if feature in ["colors", "data"]: + if feature in self.features: update_func = getattr(self, f"update_{feature}") update_func(new_data) else: raise ValueError("name arg is not a valid feature") - def _reset_feature(self, feature: str, old_data: Any, indices: Any = None): - if feature in ["colors", "data"]: + def _reset_feature(self, feature: str, old_data: Any): + if feature in self.features: update_func = getattr(self, f"update_{feature}") update_func(old_data) else: diff --git a/fastplotlib/graphics/linecollection.py b/fastplotlib/graphics/linecollection.py index 99b007681..8553749e5 100644 --- a/fastplotlib/graphics/linecollection.py +++ b/fastplotlib/graphics/linecollection.py @@ -2,10 +2,9 @@ import pygfx from typing import Union, List -from .line import LineGraphic +from fastplotlib.graphics.line import LineGraphic from typing import * -from ._base import Interaction - +from fastplotlib.graphics._base import Interaction from abc import ABC, abstractmethod @@ -26,7 +25,7 @@ def __init__(self, data: List[np.ndarray], z_position: Union[List[float], float] if not len(data) == len(cmap): raise ValueError("args must be the same length") - self.collection = list() + self.data = list() for i, d in enumerate(data): if isinstance(z_position, list): @@ -49,33 +48,30 @@ def __init__(self, data: List[np.ndarray], z_position: Union[List[float], float] else: _cmap = cmap - self.collection.append(LineGraphic(d, _z, _size, _colors, _cmap)) - - def _reset_feature(self): - pass - - @property - def indices(self) -> Any: - pass - - @indices.setter - @abstractmethod - def indices(self, indices: Any): - pass + self.data.append(LineGraphic(d, _z, _size, _colors, _cmap)) @property def features(self) -> List[str]: - pass + return ["colors", "data"] def _set_feature(self, feature: str, new_data: Any, indices: Any): - if feature in ["colors", "data"]: - update_func = getattr(self, f"update_{feature}") - self.collection[indices].update_func(new_data) + if feature in self.features: + update_func = getattr(self.data[indices], f"update_{feature}") + # if indices is a single indices or list of indices + self.data[indices].update_colors(new_data) + else: + raise ValueError("name arg is not a valid feature") + + def _reset_feature(self, feature: str, old_data: Any): + if feature in self.features: + #update_func = getattr(self, f"update_{feature}") + for i, line in enumerate(self.data): + line.update_colors(old_data[i]) else: raise ValueError("name arg is not a valid feature") def __getitem__(self, item): - return self.collection[item] + return self.data[item] From a6b53ee89e78e04f25ce53e15922384902965d11 Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Wed, 21 Dec 2022 01:36:12 -0500 Subject: [PATCH 19/19] LineCollection has @world_object, fix float64 bug in LineGraphic --- examples/linecollection_event.ipynb | 223 +++++++++++++++---------- fastplotlib/graphics/line.py | 2 +- fastplotlib/graphics/linecollection.py | 23 ++- 3 files changed, 159 insertions(+), 89 deletions(-) diff --git a/examples/linecollection_event.ipynb b/examples/linecollection_event.ipynb index a74befd36..d5aaabacf 100644 --- a/examples/linecollection_event.ipynb +++ b/examples/linecollection_event.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "id": "0c32716f-320e-4021-ad60-1c142fe6fd56", "metadata": {}, "outputs": [], @@ -13,47 +13,68 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "id": "6d72f23c-0f3a-4b2c-806d-3b239237c725", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from fastplotlib.graphics import ImageGraphic, LineCollection\n", - "from fastplotlib.plot import Plot\n", + "from fastplotlib import GridPlot\n", "import pickle" ] }, { "cell_type": "code", - "execution_count": 3, - "id": "2fb13990-63fc-4fc6-b5c1-93f8ec4c1572", + "execution_count": 2, + "id": "a8514bb3-eef5-4fd1-bcbf-9c50173a9a3c", "metadata": {}, "outputs": [], "source": [ - "contours = pickle.load(open(\"/home/caitlin/Downloads/contours.pickle\", \"rb\"))" + "def auto_scale(p):\n", + " p.camera.maintain_aspect = False\n", + " width, height, depth = np.ptp(p.scene.get_world_bounding_box(), axis=0)\n", + " p.camera.width = width\n", + " p.camera.height = height\n", + "\n", + " p.controller.distance = 0\n", + " \n", + " p.controller.zoom(0.8 / p.controller.zoom_value)" ] }, { "cell_type": "code", - "execution_count": 4, - "id": "e7970865-913e-4a58-b2eb-d262e60866de", + "execution_count": 3, + "id": "2fb13990-63fc-4fc6-b5c1-93f8ec4c1572", "metadata": {}, "outputs": [], "source": [ - "line_collection = LineCollection(data=contours, cmap=\"jet\")" + "contours = pickle.load(open(\"/home/kushal/caiman_data/contours.pickle\", \"rb\"))[0]\n", + "temporal = pickle.load(open(\"/home/kushal/caiman_data/temporal.pickle\", \"rb\"))\n", + "temporal += temporal.min()\n", + "\n", + "# make it a stack of traces\n", + "y_zero = 0\n", + "sep = 10\n", + "for i in range(1, temporal.shape[0]):\n", + " y_zero = temporal[i - 1].max()\n", + " temporal[i] += y_zero + sep\n", + "\n", + "# random colors\n", + "colors = np.random.rand(len(contours), 4).astype(np.float32)\n", + "colors[:, -1] = 1" ] }, { "cell_type": "code", - "execution_count": 5, - "id": "637d7c99-a1d6-49dc-9543-f14d49bc49ed", + "execution_count": 4, + "id": "654da73f-d20c-4a0f-bd99-13c1a52f5f5a", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8cf2ae1b21aa44d38a9814c044101394", + "model_id": "98ad6155b7c34241bd705d0f40bce8c0", "version_major": 2, "version_minor": 0 }, @@ -64,70 +85,10 @@ "metadata": {}, "output_type": "display_data" }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "MESA-INTEL: warning: Performance support disabled, consider sysctl dev.i915.perf_stream_paranoid=0\n", - "\n" - ] - } - ], - "source": [ - "plot = Plot()" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "4d89370a-d099-4ca1-96cf-bb8c8909ae65", - "metadata": {}, - "outputs": [], - "source": [ - "data = np.ones(shape=(175, 175))" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "4d302b06-e384-4cd6-bc54-56184c65523e", - "metadata": {}, - "outputs": [], - "source": [ - "img = ImageGraphic(data=data)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "52228653-e030-44a1-affc-bad45d675ea7", - "metadata": {}, - "outputs": [], - "source": [ - "for contour in line_collection:\n", - " plot.add_graphic(contour)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "4cd10499-18c8-461a-a27b-b7d7ac1bc7ea", - "metadata": {}, - "outputs": [], - "source": [ - "plot.add_graphic(img)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "6698969b-5f4b-4b19-b03a-cca6cddd78c8", - "metadata": {}, - "outputs": [ { "data": { "text/html": [ - "
initial snapshot
" + "
initial snapshot
" ], "text/plain": [ "" @@ -139,7 +100,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "3e521e3ccacc4c36921d51e75249de01", + "model_id": "8906e4b8e78c465ca05f088f105de2fc", "version_major": 2, "version_minor": 0 }, @@ -147,18 +108,73 @@ "JupyterWgpuCanvas()" ] }, - "execution_count": 10, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "# img and contour plot\n", + "plot = GridPlot(shape=(1, 2))\n", + "\n", + "data = np.ones(shape=(175, 175))\n", + "\n", + "line_collection = LineCollection(data=contours, z_position=[[1]] * len(contours), colors=colors.tolist())\n", + "plot[0, 0].add_graphic(line_collection)\n", + "\n", + "img = ImageGraphic(data=data)\n", + "plot[0, 0].add_graphic(img)\n", + "\n", + "\n", + "temporal_coll = LineCollection(data=temporal, colors=colors.tolist())\n", + "plot[0, 1].add_graphic(temporal_coll)\n", + "\n", "plot.show()" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 16, + "id": "0836f4fc-fb3b-44c6-8515-ab8d63dff52b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "line_collection._world_object.parent" + ] + }, + { + "cell_type": "markdown", + "id": "ae5fe95b-88be-48c7-a4a6-51d2818fbff0", + "metadata": {}, + "source": [ + "# you need to run this to make the stacked lineplot visible, it's easier in the latest master with camera auto-scaling" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8597de09-94aa-44cd-b480-acc1758a198c", + "metadata": {}, + "outputs": [], + "source": [ + "plot[0, 1].controller.distance = 0\n", + "auto_scale(plot[0, 1])" + ] + }, + { + "cell_type": "code", + "execution_count": 6, "id": "e321cf0d-52f7-4da2-983a-ff10653093bb", "metadata": {}, "outputs": [], @@ -170,7 +186,17 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 7, + "id": "01296977-1664-40ae-86fb-ed515fa96f4a", + "metadata": {}, + "outputs": [], + "source": [ + "white_temporal = np.ones((len(contours), 4)).astype(np.float32)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, "id": "4430e805-54db-4218-967a-30290ced8ca9", "metadata": {}, "outputs": [], @@ -180,7 +206,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "id": "c02210db-5347-4e97-a551-f4f362d3910a", "metadata": {}, "outputs": [], @@ -206,8 +232,35 @@ }, { "cell_type": "code", - "execution_count": 14, - "id": "763dc328-c47b-4240-a0e9-792c0e8b1240", + "execution_count": 11, + "id": "0fa4033f-323b-421c-84ad-da34a0ac177c", + "metadata": {}, + "outputs": [], + "source": [ + "# until we create an event \"color-changed\" (and for other graphic features)\n", + "# later we can just use the \"color-changed\" event from contour to change the lineplot or heatmap etc.\n", + "def indices_mapper_temporal(target, indices):\n", + " # global since we don't have something like \"color changed\"\n", + " # as an event which we can used for stakced line plots\n", + " global contours\n", + " coms = list()\n", + "\n", + " for contour in contours:\n", + " coors = contour[~np.isnan(contour.data).any(axis=1)]\n", + " com = coors.mean(axis=0)\n", + " coms.append(com)\n", + " \n", + " ix = np.linalg.norm((np.array(coms) - np.array(indices)), axis=1).argsort()[0]\n", + " print(ix)\n", + " \n", + " #return that index to set feature \n", + " return ix" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "0d3a3665-c9e5-42e4-9d61-c02f1f401ee2", "metadata": {}, "outputs": [], "source": [ @@ -216,11 +269,13 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "00f6039c-230f-4b90-a448-071e899d976d", + "execution_count": 13, + "id": "14fdbae1-31b7-4b58-a7e7-a50589f0ff0d", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "img.link(event_type=\"click\", target=temporal_coll, feature=\"colors\", new_data=white_temporal, indices_mapper=indices_mapper_temporal)" + ] } ], "metadata": { @@ -239,7 +294,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.10.5" } }, "nbformat": 4, diff --git a/fastplotlib/graphics/line.py b/fastplotlib/graphics/line.py index dbdef4ea2..04a58b717 100644 --- a/fastplotlib/graphics/line.py +++ b/fastplotlib/graphics/line.py @@ -28,7 +28,7 @@ def __init__(self, data: np.ndarray, z_position: float = None, size: float = 2.0 def fix_data(self): # TODO: data should probably be a property of any Graphic?? Or use set_data() and get_data() if self.data.ndim == 1: - self.data = np.dstack([np.arange(self.data.size), self.data])[0] + self.data = np.dstack([np.arange(self.data.size), self.data])[0].astype(np.float32) if self.data.shape[1] != 3: if self.data.shape[1] != 2: diff --git a/fastplotlib/graphics/linecollection.py b/fastplotlib/graphics/linecollection.py index 8553749e5..7f8adf57b 100644 --- a/fastplotlib/graphics/linecollection.py +++ b/fastplotlib/graphics/linecollection.py @@ -8,9 +8,16 @@ from abc import ABC, abstractmethod -class LineCollection(): - def __init__(self, data: List[np.ndarray], z_position: Union[List[float], float] = None, size: Union[float, List[float]] = 2.0, colors: Union[List[np.ndarray], np.ndarray] = None, - cmap: Union[List[str], str] = None, *args, **kwargs): +class LineCollection: + def __init__(self, data: List[np.ndarray], + z_position: Union[List[float], float] = None, + size: Union[float, List[float]] = 2.0, + colors: Union[List[np.ndarray], np.ndarray] = None, + cmap: Union[List[str], str] = None, + *args, + **kwargs): + + self.name = None if not isinstance(z_position, float) and z_position is not None: if not len(data) == len(z_position): @@ -26,6 +33,7 @@ def __init__(self, data: List[np.ndarray], z_position: Union[List[float], float] raise ValueError("args must be the same length") self.data = list() + self._world_object = pygfx.Group() for i, d in enumerate(data): if isinstance(z_position, list): @@ -48,7 +56,14 @@ def __init__(self, data: List[np.ndarray], z_position: Union[List[float], float] else: _cmap = cmap - self.data.append(LineGraphic(d, _z, _size, _colors, _cmap)) + lg = LineGraphic(d, _z, _size, _colors, _cmap) + self.data.append(lg) + self._world_object.add(lg.world_object) + + # TODO: make a base class for Collection graphics and put this as a base method + @property + def world_object(self) -> pygfx.WorldObject: + return self._world_object @property def features(self) -> List[str]: