Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

linear region selector #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a12ff01
linear region selector with basic functionality but wonky control
kushalkolar Mar 5, 2023
8553dc8
fix frame_apply. new: grid_plot_kwargs, reset_vmin_vmax()
kushalkolar Mar 8, 2023
72bdc88
add grid_plot_kwargs to ImageWidget docstring
kushalkolar Mar 8, 2023
5161429
better init of controllers for GridPlot, now allows controller object…
kushalkolar Mar 8, 2023
9484594
Merge pull request #148 from kushalkolar/image_fixes
kushalkolar Mar 9, 2023
216216a
make feature buffer public, make isolated buffer optional for Image a…
kushalkolar Mar 9, 2023
63fe7b7
Merge pull request #150 from kushalkolar/better-buffer-handling
kushalkolar Mar 9, 2023
172a86d
bugfix, event handler is private
kushalkolar Mar 9, 2023
350f359
temporary workaround for image and heatmap data buffers
kushalkolar Mar 9, 2023
90e8e77
Merge pull request #151 from kushalkolar/fix-image-data-feature
kushalkolar Mar 9, 2023
5c39f2e
fix docstring typo
kushalkolar Mar 25, 2023
8221a94
fixes #155
kushalkolar Mar 29, 2023
ad4a1a2
Merge pull request #156 from kushalkolar/fix-iw-reset-vminvmax
kushalkolar Mar 29, 2023
6d4141b
bugfix gridplot camears as list
kushalkolar Mar 30, 2023
8ffab35
proper garbage collection of WorldObject, implemented and works for I…
kushalkolar Apr 3, 2023
7e087db
gc works for Line, LineCollection, Scatter not tested, regular RAM is…
kushalkolar Apr 3, 2023
9713a4c
nb to explore garbage collection
kushalkolar Apr 3, 2023
247b44b
heatmap deletion frees up GPU VRAM
kushalkolar Apr 3, 2023
5e9f544
GPU VRAM and system RAM freed for all graphics
kushalkolar Apr 4, 2023
a05229c
update gc nb
kushalkolar Apr 4, 2023
1f54d31
line slider works, not gc but not necessary for now
kushalkolar Apr 4, 2023
add412f
update gc nb
kushalkolar Apr 4, 2023
d97a99d
bugfix
kushalkolar Apr 5, 2023
5a084c0
fix bug in graphic collection
clewis7 Apr 5, 2023
0cbe368
bugfix pygfx events triggered by worldobject
kushalkolar Apr 11, 2023
c9c6c78
Merge pull request #160 from kushalkolar/better-gc
kushalkolar Apr 13, 2023
40813d5
updated w.r.t. controllers, cameras, and Texture refactor. tested exa…
kushalkolar Apr 14, 2023
7fcb819
update simple.ipynb
kushalkolar Apr 14, 2023
66fd98c
bump VERSION
kushalkolar Apr 14, 2023
e4962ca
Merge pull request #163 from kushalkolar/pygfx-apr2023-refactor
kushalkolar Apr 14, 2023
7057059
linear region selector with basic functionality but wonky control
kushalkolar Mar 5, 2023
3480741
Merge branch 'selectors' of https://github.com/kushalkolar/fastplotli…
kushalkolar Apr 14, 2023
ab22259
linear region selector with basic functionality but wonky control
kushalkolar Mar 5, 2023
8c3e84d
Merge branch 'selectors' of https://github.com/kushalkolar/fastplotli…
kushalkolar Apr 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
419 changes: 419 additions & 0 deletions 419 examples/garbage_collection.ipynb

Large diffs are not rendered by default.

575 changes: 109 additions & 466 deletions 575 examples/simple.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion 2 fastplotlib/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0.a9
0.1.0.a10
76 changes: 55 additions & 21 deletions 76 fastplotlib/graphics/_base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import *
import weakref
from warnings import warn

import numpy as np
Expand All @@ -14,6 +15,11 @@
from dataclasses import dataclass


# dict that holds all world objects for a given python kernel/session
# Graphic objects only use proxies to WorldObjects
WORLD_OBJECTS: Dict[str, WorldObject] = dict() #: {hex id str: WorldObject}


PYGFX_EVENTS = [
"key_down",
"key_up",
Expand Down Expand Up @@ -44,7 +50,8 @@ def __init_subclass__(cls, **kwargs):

class Graphic(BaseGraphic):
def __init__(
self, name: str = None):
self, name: str = None
):
"""

Parameters
Expand All @@ -58,10 +65,16 @@ def __init__(
self.registered_callbacks = dict()
self.present = PresentFeature(parent=self)

# store hex id str of Graphic instance mem location
self.loc: str = hex(id(self))

@property
def world_object(self) -> WorldObject:
"""Associated pygfx WorldObject."""
return self._world_object
"""Associated pygfx WorldObject. Always returns a proxy, real object cannot be accessed directly."""
return weakref.proxy(WORLD_OBJECTS[hex(id(self))])

def _set_world_object(self, wo: WorldObject):
WORLD_OBJECTS[hex(id(self))] = wo

@property
def position(self) -> Vector3:
Expand All @@ -75,7 +88,7 @@ def visible(self) -> bool:
return self.world_object.visible

@visible.setter
def visible(self, v) -> bool:
def visible(self, v: bool):
"""Access or change the visibility."""
self.world_object.visible = v

Expand All @@ -100,6 +113,9 @@ def __repr__(self):
else:
return rval

def __del__(self):
del WORLD_OBJECTS[self.loc]


class Interaction(ABC):
"""Mixin class that makes graphics interactive"""
Expand Down Expand Up @@ -159,7 +175,7 @@ def link(

"""
if event_type in PYGFX_EVENTS:
self.world_object.add_event_handler(self.event_handler, event_type)
self.world_object.add_event_handler(self._event_handler, event_type)

# make sure event is valid
elif event_type in self.feature_events:
Expand Down Expand Up @@ -216,8 +232,13 @@ def _event_handler(self, event):

# for now we only have line collections so this works
else:
for i, item in enumerate(self._graphics):
if item.world_object is event.pick_info["world_object"]:
# get index of world object that made this event
for i, item in enumerate(self.graphics):
wo = WORLD_OBJECTS[item.loc]
# we only store hex id of worldobject, but worldobject `pick_info` is always the real object
# so if pygfx worldobject triggers an event by itself, such as `click`, etc., this will be
# the real world object in the pick_info and not the proxy
if wo is event.pick_info["world_object"]:
indices = i
target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data, indices=indices)
else:
Expand Down Expand Up @@ -264,22 +285,21 @@ class PreviouslyModifiedData:
indices: Any


COLLECTION_GRAPHICS: dict[str, Graphic] = dict()


class GraphicCollection(Graphic):
"""Graphic Collection base class"""

def __init__(self, name: str = None):
super(GraphicCollection, self).__init__(name)
self._graphics: List[Graphic] = list()

@property
def world_object(self) -> Group:
"""Returns the underling pygfx WorldObject."""
return self._world_object
self._graphics: List[str] = list()

@property
def graphics(self) -> Tuple[Graphic]:
"""returns the Graphics within this collection"""
return tuple(self._graphics)
"""The Graphics within this collection. Always returns a proxy to the Graphics."""
proxies = [weakref.proxy(COLLECTION_GRAPHICS[loc]) for loc in self._graphics]
return tuple(proxies)

def add_graphic(self, graphic: Graphic, reset_index: True):
"""Add a graphic to the collection"""
Expand All @@ -289,17 +309,31 @@ def add_graphic(self, graphic: Graphic, reset_index: True):
f"You can only add {self.child_type} to a {self.__class__.__name__}, "
f"you are trying to add a {graphic.__class__.__name__}."
)
self._graphics.append(graphic)

loc = hex(id(graphic))
COLLECTION_GRAPHICS[loc] = graphic

self._graphics.append(loc)
if reset_index:
self._reset_index()
self.world_object.add(graphic.world_object)

def remove_graphic(self, graphic: Graphic, reset_index: True):
"""Remove a graphic from the collection"""
self._graphics.remove(graphic)
self._graphics.remove(graphic.loc)

if reset_index:
self._reset_index()
self.world_object.remove(graphic)

self.world_object.remove(graphic.world_object)

def __del__(self):
self.world_object.clear()

for loc in self._graphics:
del COLLECTION_GRAPHICS[loc]

super().__del__()

def _reset_index(self):
for new_index, graphic in enumerate(self._graphics):
Expand All @@ -312,7 +346,7 @@ def __getitem__(self, key):
if isinstance(key, slice):
key = cleanup_slice(key, upper_bound=len(self))
selection_indices = range(key.start, key.stop, key.step)
selection = self._graphics[key]
selection = self.graphics[key]

# fancy-ish indexing
elif isinstance(key, (tuple, list, np.ndarray)):
Expand All @@ -324,7 +358,7 @@ def __getitem__(self, key):
selection = list()

for ix in key:
selection.append(self._graphics[ix])
selection.append(self.graphics[ix])

selection_indices = key
else:
Expand Down Expand Up @@ -365,7 +399,7 @@ def __init__(
selection_indices: Union[list, range]
the corresponding indices from the parent GraphicCollection that were selected
"""
self._parent = parent
self._parent = weakref.proxy(parent)
self._selection = selection
self._selection_indices = selection_indices

Expand Down
13 changes: 7 additions & 6 deletions 13 fastplotlib/graphics/features/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from inspect import getfullargspec
from warnings import warn
from typing import *
import weakref

import numpy as np
from pygfx import Buffer
from pygfx import Buffer, Texture


supported_dtypes = [
Expand Down Expand Up @@ -71,7 +72,7 @@ def __init__(self, parent, data: Any, collection_index: int = None):
if part of a collection, index of this graphic within the collection

"""
self._parent = parent
self._parent = weakref.proxy(parent)

self._data = to_gpu_supported_dtype(data)

Expand Down Expand Up @@ -226,7 +227,7 @@ def _update_range(self, key):

@property
@abstractmethod
def _buffer(self) -> Buffer:
def buffer(self) -> Union[Buffer, Texture]:
pass

@property
Expand All @@ -238,21 +239,21 @@ def _update_range_indices(self, key):
key = cleanup_slice(key, self._upper_bound)

if isinstance(key, int):
self._buffer.update_range(key, size=1)
self.buffer.update_range(key, size=1)
return

# else if it's a slice obj
if isinstance(key, slice):
if key.step == 1: # we cleaned up the slice obj so step of None becomes 1
# update range according to size using the offset
self._buffer.update_range(offset=key.start, size=key.stop - key.start)
self.buffer.update_range(offset=key.start, size=key.stop - key.start)

else:
step = key.step
# convert slice to indices
ixs = range(key.start, key.stop, step)
for ix in ixs:
self._buffer.update_range(ix, size=1)
self.buffer.update_range(ix, size=1)
else:
raise TypeError("must pass int or slice to update range")

16 changes: 8 additions & 8 deletions 16 fastplotlib/graphics/features/_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

class ColorFeature(GraphicFeatureIndexable):
@property
def _buffer(self):
def buffer(self):
return self._parent.world_object.geometry.colors

def __getitem__(self, item):
return self._buffer.data[item]
return self.buffer.data[item]

def __init__(self, parent, colors, n_colors: int, alpha: float = 1.0, collection_index: int = None):
"""
Expand Down Expand Up @@ -113,7 +113,7 @@ def __setitem__(self, key, value):
raise ValueError("fancy indexing for colors must be 2-dimension, i.e. [n_datapoints, RGBA]")

# set the user passed data directly
self._buffer.data[key] = value
self.buffer.data[key] = value

# update range
# first slice obj is going to be the indexing so use key[0]
Expand Down Expand Up @@ -162,7 +162,7 @@ def __setitem__(self, key, value):
else:
raise ValueError("numpy array passed to color must be of shape (4,) or (n_colors_modify, 4)")

self._buffer.data[key] = new_colors
self.buffer.data[key] = new_colors

self._update_range(key)
self._feature_changed(key, new_colors)
Expand Down Expand Up @@ -220,8 +220,8 @@ def __init__(self, parent, cmap: str):
self.name = cmap

def _set(self, cmap_name: str):
self._parent.world_object.material.map.texture.data[:] = make_colors(256, cmap_name)
self._parent.world_object.material.map.texture.update_range((0, 0, 0), size=(256, 1, 1))
self._parent.world_object.material.map.data[:] = make_colors(256, cmap_name)
self._parent.world_object.material.map.update_range((0, 0, 0), size=(256, 1, 1))
self.name = cmap_name

self._feature_changed(key=None, new_data=self.name)
Expand All @@ -246,8 +246,8 @@ class HeatmapCmapFeature(ImageCmapFeature):
"""

def _set(self, cmap_name: str):
self._parent._material.map.texture.data[:] = make_colors(256, cmap_name)
self._parent._material.map.texture.update_range((0, 0, 0), size=(256, 1, 1))
self._parent._material.map.data[:] = make_colors(256, cmap_name)
self._parent._material.map.update_range((0, 0, 0), size=(256, 1, 1))
self.name = cmap_name

self._feature_changed(key=None, new_data=self.name)
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.