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

catch up with pygfx refactor of of cameras, controllers, and Texture #163

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 3 commits into from
Apr 14, 2023
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
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
8 changes: 4 additions & 4 deletions 8 fastplotlib/graphics/features/_colors.py
Original file line number Diff line number Diff line change
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)
8 changes: 4 additions & 4 deletions 8 fastplotlib/graphics/features/_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import *

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

from ._base import GraphicFeatureIndexable, cleanup_slice, FeatureEvent, to_gpu_supported_dtype

Expand Down Expand Up @@ -87,7 +87,7 @@ def _feature_changed(self, key, new_data):

class ImageDataFeature(GraphicFeatureIndexable):
"""
Access to the TextureView buffer shown in an ImageGraphic.
Access to the Texture buffer shown in an ImageGraphic.
"""

def __init__(self, parent, data: Any):
Expand All @@ -102,7 +102,7 @@ def __init__(self, parent, data: Any):
@property
def buffer(self) -> Texture:
"""Texture buffer for the image data"""
return self._parent.world_object.geometry.grid.texture
return self._parent.world_object.geometry.grid

def update_gpu(self):
"""Update the GPU with the buffer"""
Expand Down Expand Up @@ -153,7 +153,7 @@ class HeatmapDataFeature(ImageDataFeature):
@property
def buffer(self) -> List[Texture]:
"""list of Texture buffer for the image data"""
return [img.geometry.grid.texture for img in self._parent.world_object.children]
return [img.geometry.grid for img in self._parent.world_object.children]

def update_gpu(self):
"""Update the GPU with the buffer"""
Expand Down
31 changes: 11 additions & 20 deletions 31 fastplotlib/graphics/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import numpy as np
import pygfx
from pygfx.utils import unpack_bitfield

from ._base import Graphic, Interaction, PreviouslyModifiedData
from .features import ImageCmapFeature, ImageDataFeature, HeatmapDataFeature, HeatmapCmapFeature
Expand Down Expand Up @@ -87,18 +86,18 @@ def __init__(
if (vmin is None) or (vmax is None):
vmin, vmax = quick_min_max(data)

texture_view = pygfx.Texture(buffer_init, dim=2).get_view(filter=filter)
texture = pygfx.Texture(buffer_init, dim=2)

geometry = pygfx.Geometry(grid=texture_view)
geometry = pygfx.Geometry(grid=texture)

# if data is RGB
if data.ndim == 3:
self.cmap = None
material = pygfx.ImageBasicMaterial(clim=(vmin, vmax))
material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map_interpolation=filter)
# if data is just 2D without color information, use colormap LUT
else:
self.cmap = ImageCmapFeature(self, cmap)
material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap())
material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap(), map_interpolation=filter)

world_object = pygfx.Image(
geometry,
Expand Down Expand Up @@ -151,21 +150,13 @@ class _ImageTile(pygfx.Image):
"""
Similar to pygfx.Image, only difference is that it contains a few properties to keep track of
row chunk index, column chunk index


"""
def _wgpu_get_pick_info(self, pick_value):
tex = self.geometry.grid
if hasattr(tex, "texture"):
tex = tex.texture # tex was a view
# This should match with the shader
values = unpack_bitfield(pick_value, wobject_id=20, x=22, y=22)
x = values["x"] / 4194304 * tex.size[0] - 0.5
y = values["y"] / 4194304 * tex.size[1] - 0.5
ix, iy = int(x + 0.5), int(y + 0.5)
pick_info = super()._wgpu_get_pick_info(pick_value)

# add row chunk and col chunk index to pick_info dict
return {
"index": (ix, iy),
"pixel_coord": (x - ix, y - iy),
**pick_info,
"row_chunk_index": self.row_chunk_index,
"col_chunk_index": self.col_chunk_index
}
Expand Down Expand Up @@ -281,7 +272,7 @@ def __init__(
vmin, vmax = quick_min_max(data)

self.cmap = HeatmapCmapFeature(self, cmap)
self._material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap())
self._material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap(), map_interpolation=filter)

for start, stop, chunk in zip(start_ixs, stop_ixs, chunks):
row_start, col_start = start
Expand All @@ -290,8 +281,8 @@ def __init__(
# x and y positions of the Tile in world space coordinates
y_pos, x_pos = row_start, col_start

tex_view = pygfx.Texture(buffer_init[row_start:row_stop, col_start:col_stop], dim=2).get_view(filter=filter)
geometry = pygfx.Geometry(grid=tex_view)
texture = pygfx.Texture(buffer_init[row_start:row_stop, col_start:col_stop], dim=2)
geometry = pygfx.Geometry(grid=texture)
# material = pygfx.ImageBasicMaterial(clim=(0, 1), map=self.cmap())

img = _ImageTile(geometry, self._material)
Expand Down
53 changes: 13 additions & 40 deletions 53 fastplotlib/layouts/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,11 @@ def __init__(
self._camera = camera
self._controller = controller

self.controller.add_default_event_handlers(
self.controller.add_camera(self.camera)
self.controller.register_events(
self.viewport,
self.camera
)

# camera.far and camera.near clipping planes get
# wonky with setting controller.distance = 0
if isinstance(self.camera, OrthographicCamera):
self.controller.distance = 0
# also set a initial zoom
self.controller.zoom(0.8 / self.controller.zoom_value)

self.renderer.add_event_handler(self.set_viewport_rect, "resize")

# list of hex id strings for all graphics managed by this PlotArea
Expand Down Expand Up @@ -158,7 +151,6 @@ def set_viewport_rect(self, *args):

def render(self):
# does not flush
self.controller.update_camera(self.camera)
self.viewport.render(self.scene, self.camera)

for child in self.children:
Expand Down Expand Up @@ -213,17 +205,7 @@ def _check_graphic_name_exists(self, name):
if name in graphic_names:
raise ValueError(f"graphics must have unique names, current graphic names are:\n {graphic_names}")

def _refresh_camera(self):
self.controller.update_camera(self.camera)
if sum(self.renderer.logical_size) > 0:
scene_lsize = self.viewport.rect[2], self.viewport.rect[3]
else:
scene_lsize = (1, 1)

self.camera.set_view_size(*scene_lsize)
self.camera.update_projection_matrix()

def center_graphic(self, graphic: Graphic, zoom: float = 1.3):
def center_graphic(self, graphic: Graphic, zoom: float = 1.35):
"""
Center the camera w.r.t. the passed graphic

Expand All @@ -236,17 +218,14 @@ def center_graphic(self, graphic: Graphic, zoom: float = 1.3):
zoom the camera after centering

"""
if not isinstance(self.camera, OrthographicCamera):
warn("`center_graphic()` not yet implemented for `PerspectiveCamera`")
return

self._refresh_camera()
self.camera.show_object(graphic.world_object)

self.controller.show_object(self.camera, graphic.world_object)
# camera.show_object can cause the camera width and height to increase so apply a zoom to compensate
# probably because camera.show_object uses bounding sphere
self.camera.zoom = zoom

self.controller.zoom(zoom)

def center_scene(self, zoom: float = 1.3):
def center_scene(self, zoom: float = 1.35):
"""
Auto-center the scene, does not scale.

Expand All @@ -259,15 +238,11 @@ def center_scene(self, zoom: float = 1.3):
if not len(self.scene.children) > 0:
return

if not isinstance(self.camera, OrthographicCamera):
warn("`center_scene()` not yet implemented for `PerspectiveCamera`")
return

self._refresh_camera()
self.camera.show_object(self.scene)

self.controller.show_object(self.camera, self.scene)

self.controller.zoom(zoom)
# camera.show_object can cause the camera width and height to increase so apply a zoom to compensate
# probably because camera.show_object uses bounding sphere
self.camera.zoom = zoom

def auto_scale(self, maintain_aspect: bool = False, zoom: float = 0.8):
"""
Expand Down Expand Up @@ -303,9 +278,7 @@ def auto_scale(self, maintain_aspect: bool = False, zoom: float = 0.8):
self.camera.width = width
self.camera.height = height

# self.controller.distance = 0

self.controller.zoom(zoom / self.controller.zoom_value)
self.camera.zoom = zoom

def remove_graphic(self, graphic: Graphic):
"""
Expand Down
4 changes: 2 additions & 2 deletions 4 fastplotlib/layouts/_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

controller_types = {
'2d': pygfx.PanZoomController,
'3d': pygfx.OrbitOrthoController,
'3d': pygfx.OrbitController,
pygfx.OrthographicCamera: pygfx.PanZoomController,
pygfx.PerspectiveCamera: pygfx.OrbitOrthoController,
pygfx.PerspectiveCamera: pygfx.OrbitController,
}


Expand Down
4 changes: 2 additions & 2 deletions 4 fastplotlib/layouts/_subplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from inspect import signature, getfullargspec
from warnings import warn

from pygfx import Scene, OrthographicCamera, PanZoomController, OrbitOrthoController, \
from pygfx import Scene, OrthographicCamera, PanZoomController, OrbitController, \
AxesHelper, GridHelper, WgpuRenderer
from wgpu.gui.auto import WgpuCanvas

Expand All @@ -22,7 +22,7 @@ def __init__(
position: Tuple[int, int] = None,
parent_dims: Tuple[int, int] = None,
camera: str = '2d',
controller: Union[PanZoomController, OrbitOrthoController] = None,
controller: Union[PanZoomController, OrbitController] = None,
canvas: WgpuCanvas = None,
renderer: WgpuRenderer = None,
name: str = None,
Expand Down
2 changes: 1 addition & 1 deletion 2 fastplotlib/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def __init__(
canvas: WgpuCanvas = None,
renderer: pygfx.Renderer = None,
camera: str = '2d',
controller: Union[pygfx.PanZoomController, pygfx.OrbitOrthoController] = None,
controller: Union[pygfx.PanZoomController, pygfx.OrbitController] = None,
**kwargs
):
"""
Expand Down
2 changes: 1 addition & 1 deletion 2 fastplotlib/utils/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def make_colors(n_colors: int, cmap: str, alpha: float = 1.0) -> np.ndarray:

def get_cmap_texture(name: str, alpha: float = 1.0) -> Texture:
cmap = _get_cmap(name)
return Texture(cmap, dim=1).get_view()
return Texture(cmap, dim=1)


def make_colors_dict(labels: iter, cmap: str, **kwargs) -> OrderedDict:
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.