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]: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy