Source code for ipyvolume.volume

import ipywidgets as widgets
import ipywidgets

from traitlets import Unicode, Integer
import traitlets
from traittypes import Array
import logging
import numpy as np
from .serialize import array_cube_png_serialization, array_serialization, array_binary_serialization, \
    create_array_binary_serialization
from .transferfunction import *
import warnings
import ipyvolume

logger = logging.getLogger("ipyvolume")

_last_volume_renderer = None

@widgets.register('ipyvolume.Scatter')
class Scatter(widgets.DOMWidget):
    _view_name = Unicode('ScatterView').tag(sync=True)
    _view_module = Unicode('ipyvolume').tag(sync=True)
    _model_name = Unicode('ScatterModel').tag(sync=True)
    _model_module = Unicode('ipyvolume').tag(sync=True)
    x = Array(default_value=None).tag(sync=True, **create_array_binary_serialization('x'))
    y = Array(default_value=None).tag(sync=True, **create_array_binary_serialization('y'))
    z = Array(default_value=None).tag(sync=True, **create_array_binary_serialization('z'))
    vx = Array(default_value=None,allow_none=True).tag(sync=True, **create_array_binary_serialization('vx'))
    vy = Array(default_value=None,allow_none=True).tag(sync=True, **create_array_binary_serialization('vy'))
    vz = Array(default_value=None,allow_none=True).tag(sync=True, **create_array_binary_serialization('vz'))
    selected = Array(default_value=None,allow_none=True).tag(sync=True, **array_serialization)
    sequence_index = Integer(default_value=0).tag(sync=True)
    size = traitlets.Union([traitlets.Float().tag(sync=True),
                           Array(default_value=None,allow_none=True).tag(sync=True, **array_serialization)],
                           default_value=0.1).tag(sync=True)
    size_selected = traitlets.Float(0.02).tag(sync=True)
    color = traitlets.Union([Unicode().tag(sync=True),
                             Array(default_value=None,allow_none=True).tag(sync=True, **array_serialization)],
                             default_value="red").tag(sync=True)
    color_selected = traitlets.Unicode(default_value="white").tag(sync=True)
    geo = traitlets.Unicode('diamond').tag(sync=True)



@widgets.register('ipyvolume.VolumeRendererThree')
class VolumeRendererThree(widgets.DOMWidget):
    """Widget class representing a volume (rendering) using three.js"""
    _view_name = Unicode('VolumeRendererThreeView').tag(sync=True)
    _view_module = Unicode('ipyvolume').tag(sync=True)
    _model_name = Unicode('VolumeRendererThreeModel').tag(sync=True)
    _model_module = Unicode('ipyvolume').tag(sync=True)

    volume_data = Array(default_value=None, allow_none=True).tag(sync=True, **array_cube_png_serialization)
    data_min = traitlets.CFloat().tag(sync=True)
    data_max = traitlets.CFloat().tag(sync=True)
    tf = traitlets.Instance(TransferFunction, allow_none=True).tag(sync=True, **ipywidgets.widget_serialization)
    angle1 = traitlets.Float(0.1).tag(sync=True)
    angle2 = traitlets.Float(0.2).tag(sync=True)

    scatters = traitlets.List(traitlets.Instance(Scatter), [], allow_none=False).tag(sync=True, **ipywidgets.widget_serialization)

    animation = traitlets.Float(1000.0).tag(sync=True)
    animation_exponent = traitlets.Float(.5).tag(sync=True)

    ambient_coefficient = traitlets.Float(0.5).tag(sync=True)
    diffuse_coefficient = traitlets.Float(0.8).tag(sync=True)
    specular_coefficient = traitlets.Float(0.5).tag(sync=True)
    specular_exponent = traitlets.Float(5).tag(sync=True)
    stereo = traitlets.Bool(False).tag(sync=True)
    screen_capture_enabled = traitlets.Bool(False).tag(sync=True)
    screen_capture_mime_type = traitlets.Unicode(default_value='image/png').tag(sync=True)
    screen_capture_data = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
    fullscreen = traitlets.Bool(False).tag(sync=True)

    camera_control = traitlets.Unicode(default_value='trackball').tag(sync=True)

    width = traitlets.CInt(500).tag(sync=True)
    height = traitlets.CInt(400).tag(sync=True)
    downscale = traitlets.CInt(1).tag(sync=True)
    show = traitlets.Unicode("Volume").tag(sync=True) # for debugging

    xlim = traitlets.List(traitlets.CFloat, default_value=[0, 1], minlen=2, maxlen=2).tag(sync=True)
    ylim = traitlets.List(traitlets.CFloat, default_value=[0, 1], minlen=2, maxlen=2).tag(sync=True)
    zlim = traitlets.List(traitlets.CFloat, default_value=[0, 1], minlen=2, maxlen=2).tag(sync=True)

    xlabel = traitlets.Unicode("x").tag(sync=True)
    ylabel = traitlets.Unicode("y").tag(sync=True)
    zlabel = traitlets.Unicode("z").tag(sync=True)

    style = traitlets.Dict(default_value=ipyvolume.style.default).tag(sync=True)

    #xlim = traitlets.Tuple(traitlets.CFloat(0), traitlets.CFloat(1)).tag(sync=True)
    #y#lim = traitlets.Tuple(traitlets.CFloat(0), traitlets.CFloat(1)).tag(sync=True)
    #zlim = traitlets.Tuple(traitlets.CFloat(0), traitlets.CFloat(1)).tag(sync=True)

def _volume_widets(v, lighting=False):
    import ipywidgets
    #angle1 = ipywidgets.FloatSlider(min=0, max=np.pi*2, value=v.angle1, description="angle1")
    #angle2 = ipywidgets.FloatSlider(min=0, max=np.pi*2, value=v.angle2, description="angle2")
    #ipywidgets.jslink((v, 'angle1'), (angle1, 'value'))
    #ipywidgets.jslink((v, 'angle2'), (angle2, 'value'))
    if lighting:
        ambient_coefficient = ipywidgets.FloatSlider(min=0, max=1, step=0.001, value=v.ambient_coefficient, description="ambient")
        diffuse_coefficient = ipywidgets.FloatSlider(min=0, max=1, step=0.001, value=v.diffuse_coefficient, description="diffuse")
        specular_coefficient = ipywidgets.FloatSlider(min=0, max=1, step=0.001, value=v.specular_coefficient, description="specular")
        specular_exponent = ipywidgets.FloatSlider(min=0, max=10, step=0.001, value=v.specular_exponent, description="specular exp")
        #angle2 = ipywidgets.FloatSlider(min=0, max=np.pi*2, value=v.angle2, description="angle2")
        ipywidgets.jslink((v, 'ambient_coefficient'), (ambient_coefficient, 'value'))
        ipywidgets.jslink((v, 'diffuse_coefficient'), (diffuse_coefficient, 'value'))
        ipywidgets.jslink((v, 'specular_coefficient'), (specular_coefficient, 'value'))
        ipywidgets.jslink((v, 'specular_exponent'), (specular_exponent, 'value'))
        widgets_bottom = [ipywidgets.HBox([ambient_coefficient, diffuse_coefficient]),
         ipywidgets.HBox([specular_coefficient, specular_exponent])]
    else:
        widgets_bottom = []
        v.ambient_coefficient = 1
        v.diffuse_coefficient = 0
        v.specular_coefficient = 0

    if 1:
        stereo = widgets.ToggleButton(value=v.stereo, description='stereo', icon='eye')
        fullscreen = widgets.ToggleButton(value=v.stereo, description='fullscreen', icon='arrows-alt')
        ipywidgets.jslink((v, 'stereo'), (stereo, 'value'))
        ipywidgets.jslink((v, 'fullscreen'), (fullscreen, 'value'))
        widgets_bottom += [ipywidgets.HBox([stereo,fullscreen])]

    return ipywidgets.VBox(
        [v.tf.control(), v,
         ] + widgets_bottom# , ipywidgets.HBox([angle1, angle2])
    )

[docs]def volshow(*args, **kwargs): """Deprecated: please use ipyvolume.quickvol or use the ipyvolume.pylab interface""" warnings.warn("Please use ipyvolume.quickvol or use the ipyvolume.pylab interface", DeprecationWarning, stacklevel=2) return quickvolshow(*args, **kwargs)
[docs]def quickquiver(x, y, z, u, v, w, **kwargs): import ipyvolume.pylab as p3 p3.figure() p3.quiver(x, y, z, u, v, w, **kwargs) return p3.current.container
[docs]def quickscatter(x, y, z, **kwargs): import ipyvolume.pylab as p3 p3.figure() p3.scatter(x, y, z, **kwargs) return p3.current.container
[docs]def quickvolshow(data, lighting=False, data_min=None, data_max=None, tf=None, stereo=False, width=400, height=500, ambient_coefficient=0.5, diffuse_coefficient=0.8, specular_coefficient=0.5, specular_exponent=5, downscale=1, level=[0.1, 0.5, 0.9], opacity=[0.01, 0.05, 0.1], level_width=0.1, **kwargs): """ Visualize a 3d array using volume rendering :param data: 3d numpy array :param lighting: boolean, to use lighting or not, if set to false, lighting parameters will be overriden :param data_min: minimum value to consider for data, if None, computed using np.nanmin :param data_max: maximum value to consider for data, if None, computed using np.nanmax :param tf: transfer function (see ipyvolume.transfer_function, or use the argument below) :param stereo: stereo view for virtual reality (cardboard and similar VR head mount) :param width: width of rendering surface :param height: height of rendering surface :param ambient_coefficient: lighting parameter :param diffuse_coefficient: lighting parameter :param specular_coefficient: lighting parameter :param specular_exponent: lighting parameter :param downscale: downscale the rendering for better performance, for instance when set to 2, a 512x512 canvas will show a 256x256 rendering upscaled, but it will render twice as fast. :param level: level(s) for the where the opacity in the volume peaks, maximum sequence of length 3 :param opacity: opacity(ies) for each level, scalar or sequence of max length 3 :param level_width: width of the (gaussian) bumps where the opacity peaks, scalar or sequence of max length 3 :param kwargs: extra argument passed to Volume and default transfer function :return: """ if tf is None: # TODO: should this just call the pylab interface? #tf = TransferFunctionJsBumps(**kwargs) tf_kwargs = {} # level, opacity and widths can be scalars try: level[0] except: level = [level] try: opacity[0] except: opacity = [opacity] * 3 try: level_width[0] except: level_width = [level_width] * 3 #clip off lists min_length = min(len(level), len(level_width), len(opacity)) level = list(level[:min_length]) opacity = list(opacity[:min_length]) level_width = list(level_width[:min_length]) # append with zeros while len(level) < 3: level.append(0) while len(opacity) < 3: opacity.append(0) while len(level_width) < 3: level_width.append(0) for i in range(1,4): tf_kwargs["level"+str(i)] = level[i-1] tf_kwargs["opacity"+str(i)] = opacity[i-1] tf_kwargs["width"+str(i)] = level_width[i-1] tf = TransferFunctionWidgetJs3(**tf_kwargs) if data_min is None: data_min = np.nanmin(data) if data_max is None: data_max = np.nanmax(data) v = VolumeRendererThree(volume_data=data, data_min=data_min, data_max=data_max, stereo=stereo, width=width, height=height, ambient_coefficient=ambient_coefficient, diffuse_coefficient=diffuse_coefficient, specular_coefficient=specular_coefficient, specular_exponent=specular_exponent, tf=tf, **kwargs) box = _volume_widets(v, lighting=lighting) return box
def scatter(x, y, z, color=(1,0,0), s=0.01): global _last_figure; fig = _last_figure if fig is None: fig = volshow(None) fig.scatter = Scatter(x=x, y=y, z=z, color=color, size=s) fig.volume.scatter = fig.scatter return fig