Skip to content

Commit 984737e

Browse files
authored
Cleanup (#259)
* cleanup * black * move plot to layouts * finished cleanup and flake8 config, need to figure out how to ignore long docstring tables * remove flake8 noqa * Delete setup.cfg don't want to use flake8
1 parent e001c53 commit 984737e

36 files changed

+1505
-979
lines changed

fastplotlib/__init__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from pathlib import Path
22

3-
from wgpu.gui.auto import run
3+
from .layouts import Plot, GridPlot
44

5-
from .plot import Plot
6-
from .layouts import GridPlot
5+
from wgpu.gui.auto import run
76

87
try:
98
import ipywidgets
@@ -15,3 +14,10 @@
1514

1615
with open(Path(__file__).parent.joinpath("VERSION"), "r") as f:
1716
__version__ = f.read().split("\n")[0]
17+
18+
__all__ = [
19+
"Plot",
20+
"GridPlot",
21+
"run",
22+
"ImageWidget"
23+
]

fastplotlib/graphics/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313
"HeatmapGraphic",
1414
"LineCollection",
1515
"LineStack",
16-
"TextGraphic"
16+
"TextGraphic",
1717
]

fastplotlib/graphics/_base.py

Lines changed: 84 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
from typing import *
22
import weakref
33
from warnings import warn
4+
from abc import ABC, abstractmethod
5+
from dataclasses import dataclass
46

57
import numpy as np
68

7-
from .features._base import cleanup_slice
8-
9-
from pygfx import WorldObject, Group
10-
from .features import GraphicFeature, PresentFeature, GraphicFeatureIndexable
11-
12-
from abc import ABC, abstractmethod
13-
from dataclasses import dataclass
9+
from pygfx import WorldObject
1410

11+
from ._features import GraphicFeature, PresentFeature, GraphicFeatureIndexable
1512

1613
# dict that holds all world objects for a given python kernel/session
1714
# Graphic objects only use proxies to WorldObjects
@@ -37,21 +34,22 @@
3734
class BaseGraphic:
3835
def __init_subclass__(cls, **kwargs):
3936
"""set the type of the graphic in lower case like "image", "line_collection", etc."""
40-
cls.type = cls.__name__\
41-
.lower()\
42-
.replace("graphic", "")\
43-
.replace("collection", "_collection")\
37+
cls.type = (
38+
cls.__name__.lower()
39+
.replace("graphic", "")
40+
.replace("collection", "_collection")
4441
.replace("stack", "_stack")
42+
)
4543

4644
super().__init_subclass__(**kwargs)
4745

4846

4947
class Graphic(BaseGraphic):
5048
def __init__(
51-
self,
52-
name: str = None,
53-
metadata: Any = None,
54-
collection_index: int = None,
49+
self,
50+
name: str = None,
51+
metadata: Any = None,
52+
collection_index: int = None,
5553
):
5654
"""
5755
@@ -163,6 +161,7 @@ def __del__(self):
163161

164162
class Interaction(ABC):
165163
"""Mixin class that makes graphics interactive"""
164+
166165
@abstractmethod
167166
def _set_feature(self, feature: str, new_data: Any, indices: Any):
168167
pass
@@ -172,13 +171,13 @@ def _reset_feature(self, feature: str):
172171
pass
173172

174173
def link(
175-
self,
176-
event_type: str,
177-
target: Any,
178-
feature: str,
179-
new_data: Any,
180-
callback: callable = None,
181-
bidirectional: bool = False
174+
self,
175+
event_type: str,
176+
target: Any,
177+
feature: str,
178+
new_data: Any,
179+
callback: callable = None,
180+
bidirectional: bool = False,
182181
):
183182
"""
184183
Link this graphic to another graphic upon an ``event_type`` to change the ``feature``
@@ -192,24 +191,30 @@ def link(
192191
or appropriate feature event (ex. colors, data, etc.) associated with the graphic (can use
193192
``graphic_instance.feature_events`` to get a tuple of the valid feature events for the
194193
graphic)
194+
195195
target: Any
196196
graphic to be linked to
197+
197198
feature: str
198199
feature (ex. colors, data, etc.) of the target graphic that will change following
199200
the event
201+
200202
new_data: Any
201203
appropriate data that will be changed in the feature of the target graphic after
202204
the event occurs
205+
203206
callback: callable, optional
204207
user-specified callable that will handle event,
205208
the callable must take the following four arguments
206209
| ''source'' - this graphic instance
207210
| ''target'' - the graphic to be changed following the event
208211
| ''event'' - the ''pygfx event'' or ''feature event'' that occurs
209212
| ''new_data'' - the appropriate data of the ''target'' that will be changed
213+
210214
bidirectional: bool, default False
211215
if True, the target graphic is also linked back to this graphic instance using the
212216
same arguments
217+
213218
For example:
214219
.. code-block::python
215220
@@ -231,21 +236,32 @@ def link(
231236
feature_instance.add_event_handler(self._event_handler)
232237

233238
else:
234-
raise ValueError(f"Invalid event, valid events are: {PYGFX_EVENTS + self.feature_events}")
239+
raise ValueError(
240+
f"Invalid event, valid events are: {PYGFX_EVENTS + self.feature_events}"
241+
)
235242

236243
# make sure target feature is valid
237244
if feature is not None:
238245
if feature not in target.feature_events:
239-
raise ValueError(f"Invalid feature for target, valid features are: {target.feature_events}")
246+
raise ValueError(
247+
f"Invalid feature for target, valid features are: {target.feature_events}"
248+
)
240249

241250
if event_type not in self.registered_callbacks.keys():
242251
self.registered_callbacks[event_type] = list()
243252

244-
callback_data = CallbackData(target=target, feature=feature, new_data=new_data, callback_function=callback)
253+
callback_data = CallbackData(
254+
target=target,
255+
feature=feature,
256+
new_data=new_data,
257+
callback_function=callback,
258+
)
245259

246260
for existing_callback_data in self.registered_callbacks[event_type]:
247261
if existing_callback_data == callback_data:
248-
warn("linkage already exists for given event, target, and data, skipping")
262+
warn(
263+
"linkage already exists for given event, target, and data, skipping"
264+
)
249265
return
250266

251267
self.registered_callbacks[event_type].append(callback_data)
@@ -254,15 +270,15 @@ def link(
254270
if event_type in PYGFX_EVENTS:
255271
warn("cannot use bidirectional link for pygfx events")
256272
return
257-
273+
258274
target.link(
259275
event_type=event_type,
260276
target=self,
261277
feature=feature,
262278
new_data=new_data,
263279
callback=callback,
264280
bidirectional=False # else infinite recursion, otherwise target will call
265-
# this instance .link(), and then it will happen again etc.
281+
# this instance .link(), and then it will happen again etc.
266282
)
267283

268284
def _event_handler(self, event):
@@ -271,7 +287,12 @@ def _event_handler(self, event):
271287
for target_info in self.registered_callbacks[event.type]:
272288
if target_info.callback_function is not None:
273289
# if callback_function is not None, then callback function should handle the entire event
274-
target_info.callback_function(source=self, target=target_info.target, event=event, new_data=target_info.new_data)
290+
target_info.callback_function(
291+
source=self,
292+
target=target_info.target,
293+
event=event,
294+
new_data=target_info.new_data,
295+
)
275296

276297
elif isinstance(self, GraphicCollection):
277298
# if target is a GraphicCollection, then indices will be stored in collection_index
@@ -288,16 +309,24 @@ def _event_handler(self, event):
288309
# the real world object in the pick_info and not the proxy
289310
if wo is event.pick_info["world_object"]:
290311
indices = i
291-
target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data, indices=indices)
312+
target_info.target._set_feature(
313+
feature=target_info.feature,
314+
new_data=target_info.new_data,
315+
indices=indices,
316+
)
292317
else:
293318
# if target is a single graphic, then indices do not matter
294-
target_info.target._set_feature(feature=target_info.feature, new_data=target_info.new_data,
295-
indices=None)
319+
target_info.target._set_feature(
320+
feature=target_info.feature,
321+
new_data=target_info.new_data,
322+
indices=None,
323+
)
296324

297325

298326
@dataclass
299327
class CallbackData:
300328
"""Class for keeping track of the info necessary for interactivity after event occurs."""
329+
301330
target: Any
302331
feature: str
303332
new_data: Any
@@ -329,6 +358,7 @@ def __eq__(self, other):
329358
@dataclass
330359
class PreviouslyModifiedData:
331360
"""Class for keeping track of previously modified data at indices"""
361+
332362
data: Any
333363
indices: Any
334364

@@ -350,7 +380,9 @@ def __init__(self, name: str = None):
350380
def graphics(self) -> np.ndarray[Graphic]:
351381
"""The Graphics within this collection. Always returns a proxy to the Graphics."""
352382
if self._graphics_changed:
353-
proxies = [weakref.proxy(COLLECTION_GRAPHICS[loc]) for loc in self._graphics]
383+
proxies = [
384+
weakref.proxy(COLLECTION_GRAPHICS[loc]) for loc in self._graphics
385+
]
354386
self._graphics_array = np.array(proxies)
355387
self._graphics_array.flags["WRITEABLE"] = False
356388
self._graphics_changed = False
@@ -395,15 +427,14 @@ def __getitem__(self, key):
395427
return CollectionIndexer(
396428
parent=self,
397429
selection=self.graphics[key],
398-
# selection_indices=key
399430
)
400-
431+
401432
def __del__(self):
402433
self.world_object.clear()
403434

404435
for loc in self._graphics:
405436
del COLLECTION_GRAPHICS[loc]
406-
437+
407438
super().__del__()
408439

409440
def _reset_index(self):
@@ -420,11 +451,11 @@ def __repr__(self):
420451

421452
class CollectionIndexer:
422453
"""Collection Indexer"""
454+
423455
def __init__(
424-
self,
425-
parent: GraphicCollection,
426-
selection: List[Graphic],
427-
# selection_indices: Union[list, range],
456+
self,
457+
parent: GraphicCollection,
458+
selection: List[Graphic],
428459
):
429460
"""
430461
@@ -436,26 +467,22 @@ def __init__(
436467
selection: list of Graphics
437468
a list of the selected Graphics from the parent GraphicCollection based on the ``selection_indices``
438469
439-
selection_indices: Union[list, range]
440-
the corresponding indices from the parent GraphicCollection that were selected
441470
"""
442471

443472
self._parent = weakref.proxy(parent)
444473
self._selection = selection
445-
# self._selection_indices = selection_indices
446474

447475
# we use parent.graphics[0] instead of selection[0]
448476
# because the selection can be empty
449477
for attr_name in self._parent.graphics[0].__dict__.keys():
450478
attr = getattr(self._parent.graphics[0], attr_name)
451479
if isinstance(attr, GraphicFeature):
452480
collection_feature = CollectionFeature(
453-
parent,
454-
self._selection,
455-
# selection_indices=self._selection_indices,
456-
feature=attr_name
481+
self._selection, feature=attr_name
482+
)
483+
collection_feature.__doc__ = (
484+
f"indexable <{attr_name}> feature for collection"
457485
)
458-
collection_feature.__doc__ = f"indexable <{attr_name}> feature for collection"
459486
setattr(self, attr_name, collection_feature)
460487

461488
@property
@@ -476,31 +503,26 @@ def __len__(self):
476503
return len(self._selection)
477504

478505
def __repr__(self):
479-
return f"{self.__class__.__name__} @ {hex(id(self))}\n" \
480-
f"Selection of <{len(self._selection)}> {self._selection[0].__class__.__name__}"
506+
return (
507+
f"{self.__class__.__name__} @ {hex(id(self))}\n"
508+
f"Selection of <{len(self._selection)}> {self._selection[0].__class__.__name__}"
509+
)
481510

482511

483512
class CollectionFeature:
484513
"""Collection Feature"""
485-
def __init__(
486-
self,
487-
parent: GraphicCollection,
488-
selection: List[Graphic],
489-
# selection_indices,
490-
feature: str
491-
):
514+
515+
def __init__(self, selection: List[Graphic], feature: str):
492516
"""
493-
parent: GraphicCollection
494-
GraphicCollection feature instance that is being indexed
495517
selection: list of Graphics
496518
a list of the selected Graphics from the parent GraphicCollection based on the ``selection_indices``
497-
selection_indices: Union[list, range]
498-
the corresponding indices from the parent GraphicCollection that were selected
519+
499520
feature: str
500521
feature of Graphics in the GraphicCollection being indexed
522+
501523
"""
524+
502525
self._selection = selection
503-
# self._selection_indices = selection_indices
504526
self._feature = feature
505527

506528
self._feature_instances: List[GraphicFeature] = list()
@@ -550,4 +572,3 @@ def block_events(self, b: bool):
550572

551573
def __repr__(self):
552574
return f"Collection feature for: <{self._feature}>"
553-
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from ._colors import ColorFeature, CmapFeature, ImageCmapFeature, HeatmapCmapFeature
2+
from ._data import PointsDataFeature, ImageDataFeature, HeatmapDataFeature
3+
from ._present import PresentFeature
4+
from ._thickness import ThicknessFeature
5+
from ._base import GraphicFeature, GraphicFeatureIndexable, FeatureEvent, to_gpu_supported_dtype
6+
7+
__all__ = [
8+
"ColorFeature",
9+
"CmapFeature",
10+
"ImageCmapFeature",
11+
"HeatmapCmapFeature",
12+
"PointsDataFeature",
13+
"ImageDataFeature",
14+
"HeatmapDataFeature",
15+
"PresentFeature",
16+
"ThicknessFeature",
17+
"GraphicFeature",
18+
"GraphicFeatureIndexable",
19+
"FeatureEvent",
20+
"to_gpu_supported_dtype"
21+
]

0 commit comments

Comments
 (0)