Skip to content

feat: add GPU-accelerated 3D z-stack renderer#1096

Open
keejkrej wants to merge 1 commit intoSchmollerLab:mainfrom
keejkrej:feat/3d-z-render
Open

feat: add GPU-accelerated 3D z-stack renderer#1096
keejkrej wants to merge 1 commit intoSchmollerLab:mainfrom
keejkrej:feat/3d-z-render

Conversation

@keejkrej
Copy link
Copy Markdown
Contributor

@keejkrej keejkrej commented May 6, 2026

vispy 3d rendering of z-stacks, supports overlay channel and segmentation channel
don't merge yet, haven't thoroughly tested
feel free to checkout and test

Implements a standalone vispy-based 3D volume renderer with full Cell_ACDC
integration: multi-channel overlay, segmentation mask volumes, anisotropic
voxel scaling, plane/ISO/MIP depiction modes, smooth-ISO pre-filter,
percentile auto-contrast, opacity/contrast controls, keyboard shortcuts,
QSettings persistence, and screenshot export.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 6, 2026 19:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new GPU-accelerated 3D z-stack renderer (VisPy-based) and integrates it into the main GUI as a new z-projection option, alongside a large smoke-test suite intended to validate renderer behavior without requiring an active OpenGL window.

Changes:

  • Introduces cellacdc.renderer3d with a Qt window, controls, overlay volumes, voxel anisotropy scaling, and screenshot export.
  • Integrates the renderer into gui.py via a new z-projection dropdown entry and adapter-based wiring for feeding current volumes/overlays.
  • Adds renderer3d optional dependency group (VisPy + PyOpenGL) and a new tests/test_renderer3d.py test module.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.

File Description
tests/test_renderer3d.py Adds renderer3d smoke/API/tests, including vispy-compat checks and GUI integration expectations.
pyproject.toml Adds renderer3d optional dependencies and includes them in all.
cellacdc/renderer3d.py New VisPy/Qt 3D volume renderer window, controls, overlays, voxel scaling, settings persistence, screenshot export.
cellacdc/gui.py Adds “3D z-render” mode, launches/updates/hides renderer window, and supplies current z-stack + overlays + voxel sizes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/test_renderer3d.py
def test_rendering_modes_match_vispy():
"""Every mode registered in renderer3d must be accepted by vispy.Volume."""
from cellacdc import renderer3d
import vispy
Comment thread tests/test_renderer3d.py

def test_interpolation_modes_valid_in_vispy():
"""Every INTERPOLATION_MODES id must be a valid vispy Volume interpolation."""
from cellacdc import renderer3d
Comment thread tests/test_renderer3d.py
Comment on lines +357 to +361
from cellacdc import renderer3d
import vispy
from qtpy import API_NAME
vispy.use(API_NAME)
from vispy.scene.visuals import Volume
Comment thread tests/test_renderer3d.py
Comment on lines +396 to +400
def test_depiction_plane_configs_valid_in_vispy():
"""_PLANE_CONFIGS normals must be unit vectors; vispy supports 'plane' mode."""
import vispy; from qtpy import API_NAME; vispy.use(API_NAME)
from vispy.scene.visuals import Volume
from cellacdc import renderer3d
Comment thread tests/test_renderer3d.py
Comment on lines +176 to +185
"""VolumeRenderer3DWindow must expose all expected public methods."""
from cellacdc.renderer3d import VolumeRenderer3DWindow
required = {
'update_volume', 'set_rendering_mode', 'set_colormap', 'set_clim',
'set_gamma', 'set_opacity', 'set_iso_threshold', 'set_attenuation',
'set_interpolation', 'set_step_size', 'set_smooth_iso',
'set_depiction', 'set_zplane_position', 'set_plane_thickness',
'set_voxel_scale', 'reset_view', 'save_screenshot',
'auto_contrast_percentile',
}
Comment thread tests/test_renderer3d.py
Comment on lines +591 to +595
s = QSettings(TEST_ORG, TEST_APP)
assert s.value('mode_idx', type=int) == 3
assert s.value('colormap', type=str) == 'viridis'
assert s.value('interp_idx', type=int) == 1
assert abs(s.value('clim_min', type=float) - 0.05) < 1e-6
Comment thread cellacdc/renderer3d.py
Comment on lines +93 to +97
COLORMAPS: list[str] = [
'grays', 'viridis', 'hot', 'coolwarm', 'blues', 'reds',
'greens', 'plasma', 'inferno', 'magma',
]

Comment thread cellacdc/renderer3d.py
except ImportError:
pass # scipy not available — skip smoothing silently
self._gpu_data_is_smoothed = smoothed
current_cmap = 'grays'
Comment thread cellacdc/renderer3d.py
s.setValue('clim_max', c._clim_max.value())
s.setValue('gamma', c._gamma_spin.value())
s.setValue('step_size', c._step_spin.value())
s.setValue('smooth_iso', c._smooth_iso_cb.isChecked())
Comment thread cellacdc/gui.py
Comment on lines 25346 to +25350
ol_img = img.mean(axis=0)
elif zProjHow == 'median z-proj.':
ol_img = np.median(img, axis=0)
else:
ol_img = img[z].copy()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants