class ModuleFactory(PipeFactory): """ Base class for all the modules factories""" color = Trait( None, None, TraitTuple(Range(0., 1.), Range(0., 1.), Range(0., 1.)), help="""the color of the vtk object. Overides the colormap, if any, when specified. This is specified as a triplet of float ranging from 0 to 1, eg (1, 1, 1) for white.""", ) def _color_changed(self): if self.color: self._target.actor.property.color = self.color if hasattr(self._target.actor.mapper, "scalar_visibility"): self._target.actor.mapper.scalar_visibility = False if hasattr(self._target, "property"): self._target.property.color = self.color opacity = CFloat(1., desc="""The overall opacity of the vtk object.""") def _opacity_changed(self): try: self._target.actor.property.opacity = self.opacity except AttributeError: try: self._target.property.opacity = self.opacity except AttributeError: pass line_width = CFloat(2., desc=""" The width of the lines, if any used.""") def _line_width_changed(self): try: self._target.actor.property.line_width = self.line_width except (AttributeError, TraitError): try: self._target.property.line_width = self.line_width except (AttributeError, TraitError): pass
class VolumeFactory(PipeFactory): """ Applies the Volume mayavi module to the given VTK data source (Mayavi source, or VTK dataset). **Note** The range of the colormap can be changed simply using the vmin/vmax parameters (see below). For more complex modifications of the colormap, here is some pseudo code to change the ctf (color transfer function), or the otf (opacity transfer function):: vol = mlab.pipeline.volume(src) # Changing the ctf: from tvtk.util.ctf import ColorTransferFunction ctf = ColorTransferFunction() ctf.add_rgb_point(value, r, g, b) ctf.add_hsv_point(value, h, s, v) # ... vol._volume_property.set_color(ctf) vol._ctf = ctf vol.update_ctf = True # Changing the otf: from tvtk.util.ctf import PiecewiseFunction otf = PiecewiseFunction() otf.add_point(value, opacity) vol._otf = otf vol._volume_property.set_scalar_opacity(otf) """ color = Trait(None, None, TraitTuple(Range(0., 1.),Range(0., 1.),Range(0., 1.)), help="""the color of the vtk object. Overides the colormap, if any, when specified. This is specified as a triplet of float ranging from 0 to 1, eg (1, 1, 1) for white.""", ) vmin = Trait(None, None, CFloat, help="""vmin is used to scale the transparency gradient. If None, the min of the data will be used""") vmax = Trait(None, None, CFloat, help="""vmax is used to scale the transparency gradient. If None, the max of the data will be used""") _target = Instance(modules.Volume, ()) __ctf_rescaled = Bool(False) ###################################################################### # Non-public interface. ###################################################################### def _color_changed(self): if not self.color: return range_min, range_max = self._target.current_range from tvtk.util.ctf import ColorTransferFunction ctf = ColorTransferFunction() try: ctf.range = (range_min, range_max) except Exception: # VTK versions < 5.2 don't seem to need this. pass r, g, b = self.color ctf.add_rgb_point(range_min, r, g, b) ctf.add_rgb_point(range_max, r, g, b) self._target._ctf = ctf self._target._volume_property.set_color(ctf) self._target.update_ctf = True def _vmin_changed(self): vmin = self.vmin vmax = self.vmax range_min, range_max = self._target.current_range if vmin is None: vmin = range_min if vmax is None: vmax = range_max # Change the opacity function from tvtk.util.ctf import PiecewiseFunction, save_ctfs otf = PiecewiseFunction() if range_min < vmin: otf.add_point(range_min, 0.) if range_max > vmax: otf.add_point(range_max, 0.2) otf.add_point(vmin, 0.) otf.add_point(vmax, 0.2) self._target._otf = otf self._target._volume_property.set_scalar_opacity(otf) if self.color is None and not self.__ctf_rescaled and \ ( (self.vmin is not None) or (self.vmax is not None) ): # FIXME: We don't use 'rescale_ctfs' because it screws up the nodes. def _rescale_value(x): nx = (x - range_min)/(range_max - range_min) return vmin + nx*(vmax - vmin) # The range of the existing ctf can vary. scale_min, scale_max = self._target._ctf.range def _rescale_node(x): nx = (x - scale_min)/(scale_max - scale_min) return range_min + nx*(range_max - range_min) if hasattr(self._target._ctf, 'nodes'): rgb = list() for value in self._target._ctf.nodes: r, g, b = \ self._target._ctf.get_color(value) rgb.append((_rescale_node(value), r, g, b)) else: rgb = save_ctfs(self._target.volume_property)['rgb'] from tvtk.util.ctf import ColorTransferFunction ctf = ColorTransferFunction() try: ctf.range = (range_min, range_max) except Exception: # VTK versions < 5.2 don't seem to need this. pass rgb.sort() v = rgb[0] ctf.add_rgb_point(range_min, v[1], v[2], v[3]) for v in rgb: ctf.add_rgb_point(_rescale_value(v[0]), v[1], v[2], v[3]) ctf.add_rgb_point(range_max, v[1], v[2], v[3]) self._target._ctf = ctf self._target._volume_property.set_color(ctf) self.__ctf_rescaled = True self._target.update_ctf = True
class VolumeFactory(PipeFactory): """ Applies the Volume mayavi module to the given VTK data source (Mayavi source, or VTK dataset). **Note** The range of the colormap can be changed simply using the vmin/vmax parameters (see below). For more complex modifications of the colormap, here is some pseudo code to change the ctf (color transfer function), or the otf (opacity transfer function):: vol = mlab.pipeline.volume(src) # Changing the ctf: from tvtk.util.ctf import ColorTransferFunction ctf = ColorTransferFunction() ctf.add_rgb_point(value, r, g, b) # r, g, and b are float # between 0 and 1 ctf.add_hsv_point(value, h, s, v) # ... vol._volume_property.set_color(ctf) vol._ctf = ctf vol.update_ctf = True # Changing the otf: from tvtk.util.ctf import PiecewiseFunction otf = PiecewiseFunction() otf.add_point(value, opacity) vol._otf = otf vol._volume_property.set_scalar_opacity(otf) Also, it might be useful to change the range of the ctf:: ctf.range = [0, 1] """ color = Trait( None, None, TraitTuple(Range(0., 1.), Range(0., 1.), Range(0., 1.)), help="""the color of the vtk object. Overides the colormap, if any, when specified. This is specified as a triplet of float ranging from 0 to 1, eg (1, 1, 1) for white.""", ) vmin = Trait(None, None, CFloat, help="""vmin is used to scale the transparency gradient. If None, the min of the data will be used""") vmax = Trait(None, None, CFloat, help="""vmax is used to scale the transparency gradient. If None, the max of the data will be used""") _target = Instance(modules.Volume, ()) __last_vrange = Any(None) ###################################################################### # Non-public interface. ###################################################################### def _color_changed(self): if not self.color: return range_min, range_max = self._target.current_range from tvtk.util.ctf import ColorTransferFunction ctf = ColorTransferFunction() try: ctf.range = (range_min, range_max) except Exception: # VTK versions < 5.2 don't seem to need this. pass r, g, b = self.color ctf.add_rgb_point(range_min, r, g, b) ctf.add_rgb_point(range_max, r, g, b) self._target._ctf = ctf self._target._volume_property.set_color(ctf) self._target.update_ctf = True def _vmin_changed(self): vmin = self.vmin vmax = self.vmax range_min, range_max = self._target.current_range if vmin is None: vmin = range_min if vmax is None: vmax = range_max # Change the opacity function from tvtk.util.ctf import PiecewiseFunction, save_ctfs otf = PiecewiseFunction() if range_min < vmin: otf.add_point(range_min, 0.) if range_max > vmax: otf.add_point(range_max, 0.2) otf.add_point(vmin, 0.) otf.add_point(vmax, 0.2) self._target._otf = otf self._target._volume_property.set_scalar_opacity(otf) if self.color is None and \ ((self.vmin is not None) or (self.vmax is not None)): # FIXME: We don't use 'rescale_ctfs' because it screws up the # nodes, this is because, the values are actually scaled between # the specified vmin/vmax and NOT the full range of values # specified in the CTF or in the volume object. if self.__last_vrange: last_min, last_max = self.__last_vrange else: last_min, last_max = range_min, range_max def _rescale_value(x): nx = (x - last_min) / (last_max - last_min) return vmin + nx * (vmax - vmin) # For some reason on older versions of VTK (< 8.1 at least), # The range trait is not updated correctly when the rgb points # are added, this causes problems so we explicitly update them. self._target._ctf.update_traits() scale_min, scale_max = self._target._ctf.range def _rescale_node(x): nx = (x - scale_min) / (scale_max - scale_min) return range_min + nx * (range_max - range_min) if hasattr(self._target._ctf, 'nodes'): rgb = list() for value in self._target._ctf.nodes: r, g, b = \ self._target._ctf.get_color(value) rgb.append((_rescale_node(value), r, g, b)) else: rgb = save_ctfs(self._target.volume_property)['rgb'] from tvtk.util.ctf import ColorTransferFunction ctf = ColorTransferFunction() try: ctf.range = (range_min, range_max) except Exception: # VTK versions < 5.2 don't seem to need this. pass rgb.sort() v = rgb[0] ctf.add_rgb_point(range_min, v[1], v[2], v[3]) for v in rgb: ctf.add_rgb_point(_rescale_value(v[0]), v[1], v[2], v[3]) ctf.add_rgb_point(range_max, v[1], v[2], v[3]) self._target._ctf = ctf self._target._volume_property.set_color(ctf) self.__last_vrange = vmin, vmax self._target.update_ctf = True # This is not necessary: the job is already done by _vmin_changed _vmax_changed = _vmin_changed