Skip to content

Navigation Menu

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

add size_space to pygfx.PointsMaterial scatter kwargs #689

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

Merged
merged 19 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 35 additions & 0 deletions 35 docs/source/api/graphic_features/SizeSpace.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.. _api.SizeSpace:

SizeSpace
*********

=========
SizeSpace
=========
.. currentmodule:: fastplotlib.graphics._features

Constructor
~~~~~~~~~~~
.. autosummary::
:toctree: SizeSpace_api

SizeSpace

Properties
~~~~~~~~~~
.. autosummary::
:toctree: SizeSpace_api

SizeSpace.value

Methods
~~~~~~~
.. autosummary::
:toctree: SizeSpace_api

SizeSpace.add_event_handler
SizeSpace.block_events
SizeSpace.clear_event_handlers
SizeSpace.remove_event_handler
SizeSpace.set_value

1 change: 1 addition & 0 deletions 1 docs/source/api/graphic_features/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Graphic Features
VertexColors
UniformColor
UniformSize
SizeSpace
Thickness
VertexPositions
PointsSizesFeature
Expand Down
1 change: 1 addition & 0 deletions 1 docs/source/api/graphics/LineGraphic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Properties
LineGraphic.offset
LineGraphic.right_click_menu
LineGraphic.rotation
LineGraphic.size_space
LineGraphic.supported_events
LineGraphic.thickness
LineGraphic.visible
Expand Down
1 change: 1 addition & 0 deletions 1 docs/source/api/graphics/ScatterGraphic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Properties
ScatterGraphic.offset
ScatterGraphic.right_click_menu
ScatterGraphic.rotation
ScatterGraphic.size_space
ScatterGraphic.sizes
ScatterGraphic.supported_events
ScatterGraphic.visible
Expand Down
2 changes: 2 additions & 0 deletions 2 fastplotlib/graphics/_features/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
VertexColors,
UniformColor,
UniformSize,
SizeSpace,
Thickness,
VertexPositions,
PointsSizesFeature,
Expand Down Expand Up @@ -42,6 +43,7 @@
"VertexColors",
"UniformColor",
"UniformSize",
"SizeSpace",
"Thickness",
"VertexPositions",
"PointsSizesFeature",
Expand Down
21 changes: 21 additions & 0 deletions 21 fastplotlib/graphics/_features/_positions_graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,27 @@ def set_value(self, graphic, value: float | int):
self._call_event_handlers(event)


# manages the coordinate space for scatter/line
class SizeSpace(GraphicFeature):
def __init__(self, value: str):
self._value = value
super().__init__()

@property
def value(self) -> str:
return self._value

def set_value(self, graphic, value: str):
if "Line" in graphic.world_object.material.__class__.__name__:
graphic.world_object.material.thickness_space = value
else:
graphic.world_object.material.size_space = value
self._value = value

event = FeatureEvent(type="size_space", info={"value": value})
self._call_event_handlers(event)


class VertexPositions(BufferManager):
"""
+----------+----------------------------------------------------------+------------------------------------------------------------------------------------------+
Expand Down
16 changes: 16 additions & 0 deletions 16 fastplotlib/graphics/_positions_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
UniformColor,
VertexCmap,
PointsSizesFeature,
SizeSpace,
)


Expand Down Expand Up @@ -54,6 +55,19 @@ def cmap(self, name: str):

self._cmap[:] = name

@property
def size_space(self):
"""
The coordinate space in which the size is expressed (‘screen’, ‘world’, ‘model’)

See https://docs.pygfx.org/stable/_autosummary/utils/utils/enums/pygfx.utils.enums.CoordSpace.html#pygfx.utils.enums.CoordSpace for available options.
"""
return self._size_space.value

@size_space.setter
def size_space(self, value: str):
self._size_space.set_value(self, value)

def __init__(
self,
data: Any,
Expand All @@ -63,6 +77,7 @@ def __init__(
cmap: str | VertexCmap = None,
cmap_transform: np.ndarray = None,
isolated_buffer: bool = True,
size_space: str = "screen",
*args,
**kwargs,
):
Expand Down Expand Up @@ -132,6 +147,7 @@ def __init__(
self._colors, cmap_name=None, transform=None, alpha=alpha
)

self._size_space = SizeSpace(size_space)
super().__init__(*args, **kwargs)

def unshare_property(self, property: str):
Expand Down
15 changes: 12 additions & 3 deletions 15 fastplotlib/graphics/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

from ._positions_base import PositionsGraphic
from .selectors import LinearRegionSelector, LinearSelector, RectangleSelector
from ._features import Thickness
from ._features import Thickness, SizeSpace


class LineGraphic(PositionsGraphic):
_features = {"data", "colors", "cmap", "thickness"}
_features = {"data", "colors", "cmap", "thickness", "size_space"}

def __init__(
self,
Expand All @@ -22,6 +22,7 @@ def __init__(
cmap: str = None,
cmap_transform: np.ndarray | Iterable = None,
isolated_buffer: bool = True,
size_space: str = "screen",
**kwargs,
):
"""
Expand Down Expand Up @@ -53,6 +54,9 @@ def __init__(
cmap_transform: 1D array-like of numerical values, optional
if provided, these values are used to map the colors from the cmap

size_space: str, default "screen"
coordinate space in which the size is expressed (‘screen’, ‘world’, ‘model’)

**kwargs
passed to Graphic

Expand All @@ -66,6 +70,7 @@ def __init__(
cmap=cmap,
cmap_transform=cmap_transform,
isolated_buffer=isolated_buffer,
size_space=size_space,
**kwargs,
)

Expand All @@ -83,10 +88,14 @@ def __init__(
color_mode="uniform",
color=self.colors,
pick_write=True,
thickness_space=self.size_space,
)
else:
material = MaterialCls(
thickness=self.thickness, color_mode="vertex", pick_write=True
thickness=self.thickness,
color_mode="vertex",
pick_write=True,
thickness_space=self.size_space,
)
geometry = pygfx.Geometry(
positions=self._data.buffer, colors=self._colors.buffer
Expand Down
11 changes: 9 additions & 2 deletions 11 fastplotlib/graphics/scatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import pygfx

from ._positions_base import PositionsGraphic
from ._features import PointsSizesFeature, UniformSize
from ._features import PointsSizesFeature, UniformSize, SizeSpace


class ScatterGraphic(PositionsGraphic):
_features = {"data", "sizes", "colors", "cmap"}
_features = {"data", "sizes", "colors", "cmap", "size_space"}

def __init__(
self,
Expand All @@ -21,6 +21,7 @@ def __init__(
isolated_buffer: bool = True,
sizes: float | np.ndarray | Iterable[float] = 1,
uniform_size: bool = False,
size_space: str = "screen",
**kwargs,
):
"""
Expand Down Expand Up @@ -60,6 +61,9 @@ def __init__(
if True, uses a uniform buffer for the scatter point sizes,
basically saves GPU VRAM when all scatter points are the same size

size_space: str, default "screen"
coordinate space in which the size is expressed (‘screen’, ‘world’, ‘model’)

kwargs
passed to Graphic

Expand All @@ -73,13 +77,15 @@ def __init__(
cmap=cmap,
cmap_transform=cmap_transform,
isolated_buffer=isolated_buffer,
size_space=size_space,
**kwargs,
)

n_datapoints = self.data.value.shape[0]

geo_kwargs = {"positions": self._data.buffer}
material_kwargs = {"pick_write": True}
self._size_space = SizeSpace(size_space)
FlynnOConnell marked this conversation as resolved.
Show resolved Hide resolved

if uniform_color:
material_kwargs["color_mode"] = "uniform"
Expand All @@ -97,6 +103,7 @@ def __init__(
self._sizes = PointsSizesFeature(sizes, n_datapoints=n_datapoints)
geo_kwargs["sizes"] = self.sizes.buffer

material_kwargs["size_space"] = self.size_space
world_object = pygfx.Points(
pygfx.Geometry(**geo_kwargs),
material=pygfx.PointsMaterial(**material_kwargs),
Expand Down
42 changes: 42 additions & 0 deletions 42 tests/test_positions_graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,45 @@ def test_thickness(thickness):

else:
assert isinstance(graphic.world_object.material, pygfx.LineMaterial)


@pytest.mark.parametrize("graphic_type", ["line", "scatter"])
@pytest.mark.parametrize("size_space", ["screen", "world", "model"])
def test_size_space(graphic_type, size_space):
fig = fpl.Figure()

kwargs = dict()
for kwarg in ["size_space"]:
if locals()[kwarg] is not None:
# add to dict of arguments that will be passed
kwargs[kwarg] = locals()[kwarg]

data = generate_positions_spiral_data("xy")

if size_space is None:
size_space = "screen" # default space

# size_space is really an alias for pygfx.utils.enums.CoordSpace
if graphic_type == "line":
graphic = fig[0, 0].add_line(data=data, **kwargs)

# test getter
assert graphic.world_object.material.thickness_space == size_space
assert graphic.size_space == size_space

# test setter
graphic.size_space = "world"
assert graphic.size_space == "world"
assert graphic.world_object.material.thickness_space == "world"

elif graphic_type == "scatter":

# test getter
graphic = fig[0, 0].add_scatter(data=data, **kwargs)
assert graphic.world_object.material.size_space == size_space
assert graphic.size_space == size_space

# test setter
graphic.size_space = "world"
assert graphic.size_space == "world"
assert graphic.world_object.material.size_space == "world"
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.