diff --git a/ensemble/volren/volume_axes.py b/ensemble/volren/volume_axes.py index cd82f09..4660290 100644 --- a/ensemble/volren/volume_axes.py +++ b/ensemble/volren/volume_axes.py @@ -24,15 +24,11 @@ class VolumeAxes(ABCVolumeSceneMember): # ABCVolumeSceneMember interface #-------------------------------------------------------------------------- - def add_actors_to_scene(self, scene_model): - - actor = self.find_volume_actor(scene_model) - if actor is None: - return + def add_actors_to_scene(self, scene_model, volume_actor): # Some axes with ticks if any(self.visible_axis_scales): - bounds = actor.bounds + bounds = volume_actor.bounds x_vis, y_vis, z_vis = self.visible_axis_scales x_range, y_range, z_range = self.visible_axis_ranges cube_axes = tvtk.CubeAxesActor( diff --git a/ensemble/volren/volume_bounding_box.py b/ensemble/volren/volume_bounding_box.py index 192172c..03d7cf7 100644 --- a/ensemble/volren/volume_bounding_box.py +++ b/ensemble/volren/volume_bounding_box.py @@ -12,14 +12,10 @@ class VolumeBoundingBox(ABCVolumeSceneMember): # ABCVolumeSceneMember interface #-------------------------------------------------------------------------- - def add_actors_to_scene(self, scene_model): - - actor = self.find_volume_actor(scene_model) - if actor is None: - return + def add_actors_to_scene(self, scene_model, volume_actor): # An outline of the bounds of the Volume actor's data - outline = tvtk.OutlineFilter(input=actor.mapper.input) + outline = tvtk.OutlineFilter(input=volume_actor.mapper.input) outline_mapper = tvtk.PolyDataMapper(input=outline.output) outline_actor = tvtk.Actor(mapper=outline_mapper) outline_actor.property.opacity = 0.3 diff --git a/ensemble/volren/volume_renderer.py b/ensemble/volren/volume_renderer.py index 09d4008..d4133bf 100755 --- a/ensemble/volren/volume_renderer.py +++ b/ensemble/volren/volume_renderer.py @@ -1,6 +1,6 @@ from mayavi.sources.vtk_data_source import VTKDataSource from mayavi.tools.tools import add_dataset -from traits.api import CInt, Instance, List +from traits.api import CInt, Instance, List, Property from tvtk.api import tvtk from ensemble.ctf.piecewise import PiecewiseFunction @@ -21,6 +21,9 @@ class VolumeRenderer(ABCVolumeSceneMember): # The mayavi volume renderer object volume = Instance(Volume3D) + # The tvtk.Actor for `volume` + actor = Property(Instance(tvtk.Actor), depends_on='volume') + # The minimum and maximum displayed intensity values. vmin = CInt(0) vmax = CInt(255) @@ -36,11 +39,11 @@ class VolumeRenderer(ABCVolumeSceneMember): # ABCVolumeSceneMember interface # ------------------------------------------------------------------------- - def add_actors_to_scene(self, scene_model): - sf = add_dataset(self.data.resampled_image_data, - figure=scene_model.mayavi_scene) - self.data_source = sf - self.volume = volume3d(sf, figure=scene_model.mayavi_scene) + def add_actors_to_scene(self, scene_model, volume_actor): + source = add_dataset(self.data.resampled_image_data, + figure=scene_model.mayavi_scene) + self.data_source = source + self.volume = volume3d(source, figure=scene_model.mayavi_scene) self._setup_volume() # ------------------------------------------------------------------------- @@ -57,11 +60,11 @@ def set_transfer_function(self, colors=None, opacities=None): if opacities is not None: self.opacities = opacities - ctf = tvtk.ColorTransferFunction() + color_tf = tvtk.ColorTransferFunction() for color in self.colors.items(): - ctf.add_rgb_point(lerp(color[0]), *(color[1:])) + color_tf.add_rgb_point(lerp(color[0]), *(color[1:])) - otf = tvtk.PiecewiseFunction() + opacity_tf = tvtk.PiecewiseFunction() alphas = self.opacities.items() for i, alpha in enumerate(alphas): x = alpha[0] @@ -70,21 +73,17 @@ def set_transfer_function(self, colors=None, opacities=None): # we need to jog a value that is exactly equal by a little bit. if alphas[i-1][0] == alpha[0]: x += 1e-8 - otf.add_point(lerp(x), alpha[1]) + opacity_tf.add_point(lerp(x), alpha[1]) - self._set_volume_ctf(ctf, otf) + self._set_volume_ctf(color_tf, opacity_tf) # ------------------------------------------------------------------------- - # Default values + # Traits bits # ------------------------------------------------------------------------- def _clip_bounds_default(self): return [0, CLIP_MAX, 0, CLIP_MAX, 0, CLIP_MAX] - # ------------------------------------------------------------------------- - # Traits notifications - # ------------------------------------------------------------------------- - def _data_changed(self): self.vmin = self.data.raw_data.min() self.vmax = self.data.raw_data.max() @@ -98,6 +97,9 @@ def _data_changed(self): def _clip_bounds_changed(self): self._set_volume_clip_planes() + def _get_actor(self): + return self.volume.actors[0] + # ------------------------------------------------------------------------- # Private methods # ------------------------------------------------------------------------- @@ -120,9 +122,9 @@ def _set_volume_clip_planes(self): # Set them as the clipping planes for the volume mapper self.volume.volume.mapper.clipping_planes = planes - def _set_volume_ctf(self, ctf, otf): + def _set_volume_ctf(self, color_tf, opacity_tf): if self.volume is not None: vp = self.volume.volume_property - vp.set_scalar_opacity(otf) - vp.set_color(ctf) + vp.set_scalar_opacity(opacity_tf) + vp.set_color(color_tf) self.volume._update_ctf_fired() diff --git a/ensemble/volren/volume_scene_member.py b/ensemble/volren/volume_scene_member.py index de5c476..3a0c423 100644 --- a/ensemble/volren/volume_scene_member.py +++ b/ensemble/volren/volume_scene_member.py @@ -9,20 +9,6 @@ class ABCVolumeSceneMember(ABCHasStrictTraits): """ @abstractmethod - def add_actors_to_scene(self, scene_model): + def add_actors_to_scene(self, scene_model, volume_actor): """ Add actors to the mayavi scene `scene_model`. """ - - @staticmethod - def find_volume_actor(scene_model): - """ Return the first `Volume` actor found in a Mayavi `SceneModel`. - """ - import tvtk # An expensive import that should be deferred - - volume_class = tvtk.tvtk_classes.volume.Volume - - for actor in scene_model.actor_list: - if isinstance(actor, volume_class): - return actor - - return None diff --git a/ensemble/volren/volume_viewer.py b/ensemble/volren/volume_viewer.py index 082fff9..28af282 100644 --- a/ensemble/volren/volume_viewer.py +++ b/ensemble/volren/volume_viewer.py @@ -95,11 +95,12 @@ def ctf_updated(self): @on_trait_change('model.activated') def display_model(self): # Add the volume to the scene - self.volume_renderer.add_actors_to_scene(self.model) + self.volume_renderer.add_actors_to_scene(self.model, None) # Add the other members to the scene + volume_actor = self.volume_renderer.actor for member in self.scene_members: - member.add_actors_to_scene(self.model) + member.add_actors_to_scene(self.model, volume_actor) self._setup_camera() self.model.scene.background = (0, 0, 0)