Skip to content
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

Add support for ipyvolume volume viewer #50

Merged
merged 2 commits into from
Sep 10, 2024
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
2 changes: 2 additions & 0 deletions glue_ar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ def setup_jupyter():
pass

from glue_jupyter.ipyvolume.scatter import IpyvolumeScatterView
from glue_jupyter.ipyvolume.volume import IpyvolumeVolumeView
IpyvolumeScatterView.tools = [t for t in IpyvolumeScatterView.tools] + ["save:ar_jupyter"]
IpyvolumeVolumeView.tools = [t for t in IpyvolumeVolumeView.tools] + ["save:ar_jupyter"]


def setup():
Expand Down
1 change: 1 addition & 0 deletions glue_ar/common/export_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def __call__(self,
multiple: bool = False):
def adder(export_method: Callable):
self.add(layer_state_cls, name, layer_options_state, extensions, multiple, export_method)
return export_method
return adder


Expand Down
14 changes: 12 additions & 2 deletions glue_ar/common/marching_cubes.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
(viewer_state.x_min, viewer_state.x_max),
(viewer_state.z_min, viewer_state.z_max),
)
resolution = viewer_state.resolution
resolution = getattr(viewer_state, 'resolution', None) or getattr(layer_state, 'max_resolution')

Check warning on line 43 in glue_ar/common/marching_cubes.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/common/marching_cubes.py#L43

Added line #L43 was not covered by tests
x_range = viewer_state.x_max - viewer_state.x_min
y_range = viewer_state.y_max - viewer_state.y_min
z_range = viewer_state.z_max - viewer_state.z_min
Expand Down Expand Up @@ -141,7 +141,7 @@
(viewer_state.x_min, viewer_state.x_max),
(viewer_state.z_min, viewer_state.z_max),
)
resolution = viewer_state.resolution
resolution = getattr(viewer_state, 'resolution', None) or getattr(layer_state, 'max_resolution')

Check warning on line 144 in glue_ar/common/marching_cubes.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/common/marching_cubes.py#L144

Added line #L144 was not covered by tests
x_range = viewer_state.x_max - viewer_state.x_min
y_range = viewer_state.y_max - viewer_state.y_min
z_range = viewer_state.z_max - viewer_state.z_min
Expand All @@ -164,3 +164,13 @@
points = [tuple((-1 + (index + 0.5) * side) for index, side in zip(pt, clip_sides)) for pt in points]
points = [[p[1], p[0], p[2]] for p in points]
builder.add_mesh(points, triangles, color_components, alpha)


try:
from glue_jupyter.ipyvolume.volume import VolumeLayerState as IPVVolumeLayerState
ar_layer_export.add(IPVVolumeLayerState, "Isosurface", ARIsosurfaceExportOptions,
("gltf", "glb"), False, add_isosurface_layer_gltf)
ar_layer_export.add(IPVVolumeLayerState, "Isosurface", ARIsosurfaceExportOptions,
("usda", "usdc"), False, add_isosurface_layer_usd)
except ImportError:
pass

Check warning on line 176 in glue_ar/common/marching_cubes.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/common/marching_cubes.py#L175-L176

Added lines #L175 - L176 were not covered by tests
Empty file.
16 changes: 13 additions & 3 deletions glue_ar/common/voxels.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from glue_ar.common.usd_builder import USDBuilder
from glue_ar.common.volume_export_options import ARVoxelExportOptions
from glue_ar.usd_utils import material_for_color
from glue_ar.utils import BoundsWithResolution, alpha_composite, frb_for_layer, hex_to_components, \
from glue_ar.utils import BoundsWithResolution, alpha_composite, frb_for_layer, get_resolution, hex_to_components, \
isomin_for_layer, isomax_for_layer, layer_color, unique_id, xyz_bounds

from glue_ar.gltf_utils import add_points_to_bytearray, add_triangles_to_bytearray, \
Expand All @@ -26,7 +26,7 @@
options: Iterable[ARVoxelExportOptions],
bounds: Optional[BoundsWithResolution] = None):

resolution = viewer_state.resolution
resolution = get_resolution(viewer_state)

Check warning on line 29 in glue_ar/common/voxels.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/common/voxels.py#L29

Added line #L29 was not covered by tests
bounds = bounds or xyz_bounds(viewer_state, with_resolution=True)
x_range = viewer_state.x_max - viewer_state.x_min
y_range = viewer_state.y_max - viewer_state.y_min
Expand Down Expand Up @@ -167,7 +167,7 @@
options: Iterable[ARVoxelExportOptions],
bounds: Optional[BoundsWithResolution] = None):

resolution = viewer_state.resolution
resolution = get_resolution(viewer_state)

Check warning on line 170 in glue_ar/common/voxels.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/common/voxels.py#L170

Added line #L170 was not covered by tests
bounds = bounds or xyz_bounds(viewer_state, with_resolution=True)
x_range = viewer_state.x_max - viewer_state.x_min
y_range = viewer_state.y_max - viewer_state.y_min
Expand Down Expand Up @@ -242,3 +242,13 @@
builder.add_translated_reference(mesh, translation, material)

return builder


try:
from glue_jupyter.ipyvolume.volume import VolumeLayerState as IPVVolumeLayerState
ar_layer_export.add(IPVVolumeLayerState, "Voxel", ARVoxelExportOptions,
("gltf", "glb"), True, add_voxel_layers_gltf)
ar_layer_export.add(IPVVolumeLayerState, "Voxel", ARVoxelExportOptions,
("usda", "usdc"), True, add_voxel_layers_usd)
except ImportError:
pass

Check warning on line 254 in glue_ar/common/voxels.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/common/voxels.py#L253-L254

Added lines #L253 - L254 were not covered by tests
5 changes: 2 additions & 3 deletions glue_ar/jupyter/export_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@

from glue.config import viewer_tool
from glue.viewers.common.tool import Tool
from glue_vispy_viewers.volume.qt.volume_viewer import VispyVolumeViewerMixin

from glue_ar.common.export import export_viewer
from glue_ar.jupyter.export_dialog import JupyterARExportDialog
from glue_ar.utils import AR_ICON, xyz_bounds
from glue_ar.utils import AR_ICON, is_volume_viewer, xyz_bounds

import ipyvuetify as v # noqa
from ipywidgets import HBox, Layout # noqa
Expand Down Expand Up @@ -109,7 +108,7 @@
self.viewer.output_widget.clear_output()

def save_figure(self, filepath):
bounds = xyz_bounds(self.viewer.state, with_resolution=isinstance(self.viewer, VispyVolumeViewerMixin))
bounds = xyz_bounds(self.viewer.state, with_resolution=is_volume_viewer(self.viewer))

Check warning on line 111 in glue_ar/jupyter/export_tool.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/jupyter/export_tool.py#L111

Added line #L111 was not covered by tests
layer_states = [layer.state for layer in self.viewer.layers if layer.enabled and layer.state.visible]
state_dict = self.export_dialog.state_dictionary
export_viewer(viewer_state=self.viewer.state,
Expand Down
41 changes: 36 additions & 5 deletions glue_ar/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
from glue.viewers.common.viewer import LayerArtist, Viewer

from glue_vispy_viewers.common.layer_state import LayerState, VispyLayerState
from glue_vispy_viewers.volume.volume_viewer import VispyVolumeViewerMixin
from glue_vispy_viewers.volume.layer_state import VolumeLayerState
from glue_vispy_viewers.volume.viewer_state import Vispy3DViewerState
from glue_vispy_viewers.volume.viewer_state import Vispy3DViewerState, Vispy3DVolumeViewerState
from numpy import array, inf, isnan, ndarray

try:
Expand Down Expand Up @@ -81,7 +82,8 @@
(viewer_state.y_min, viewer_state.y_max),
(viewer_state.z_min, viewer_state.z_max)]
if with_resolution:
return [(*b, viewer_state.resolution) for b in bounds]
resolution = get_resolution(viewer_state)
return [(*b, resolution) for b in bounds]

Check warning on line 86 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L85-L86

Added lines #L85 - L86 were not covered by tests

return bounds

Expand Down Expand Up @@ -110,7 +112,8 @@
maxes = [max(max(data[att]), m) for m, att in zip(maxes, atts)]
bounds = [(lo, hi) for lo, hi in zip(mins, maxes)]
if with_resolution:
return [(*b, viewer_state.resolution) for b in bounds]
resolution = get_resolution(viewer_state)
return [(*b, resolution) for b in bounds]

Check warning on line 116 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L115-L116

Added lines #L115 - L116 were not covered by tests

return bounds

Expand Down Expand Up @@ -216,8 +219,9 @@
data = data_for_layer(layer_or_state)
layer_state = layer_or_state if isinstance(layer_or_state, LayerState) else layer_or_state.state
is_data_layer = data is layer_or_state.layer
target_data = getattr(viewer_state, 'reference_data', data)

Check warning on line 222 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L222

Added line #L222 was not covered by tests
data_frb = data.compute_fixed_resolution_buffer(
target_data=viewer_state.reference_data,
target_data=target_data,
bounds=bounds,
target_cid=layer_state.attribute
)
Expand All @@ -226,7 +230,7 @@
return data_frb
else:
subcube = data.compute_fixed_resolution_buffer(
target_data=viewer_state.reference_data,
target_data=target_data,
bounds=bounds,
subset_state=layer_state.layer.subset_state
)
Expand All @@ -247,3 +251,30 @@
Note that this consumes the iterator.
"""
return sum(1 for _ in iter)


def is_volume_viewer(viewer: Viewer) -> bool:
if isinstance(viewer, VispyVolumeViewerMixin):
return True
try:
from glue_jupyter.ipyvolume.volume import IpyvolumeVolumeView
if isinstance(viewer, IpyvolumeVolumeView):
return True
except ImportError:
pass

Check warning on line 264 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L257-L264

Added lines #L257 - L264 were not covered by tests

return False

Check warning on line 266 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L266

Added line #L266 was not covered by tests


def get_resolution(viewer_state: Viewer3DState) -> int:
if isinstance(viewer_state, Vispy3DVolumeViewerState):
return viewer_state.resolution

Check warning on line 271 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L270-L271

Added lines #L270 - L271 were not covered by tests

try:
from glue_jupyter.common.state3d import VolumeViewerState
if isinstance(viewer_state, VolumeViewerState):
return max((getattr(state, 'max_resolution', 256) for state in viewer_state.layers), default=256)
except ImportError:
pass

Check warning on line 278 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L273-L278

Added lines #L273 - L278 were not covered by tests

return 256

Check warning on line 280 in glue_ar/utils.py

View check run for this annotation

Codecov / codecov/patch

glue_ar/utils.py#L280

Added line #L280 was not covered by tests