TODO:

  • use sympy to generate the file to show
  • show how to do the line plot using VTK
  • make sure the slider works

In [1]:
from cStringIO import StringIO

def figure2png(fig):
        buffer = StringIO()
        fig.savefig(buffer, format='png')
        buffer.reset()
        data = buffer.read().encode('base64')
        return "data:image/png;base64,{0}".format(data.replace('\n', ''))
    

class Slider(object):
    
    def __init__(self, python_var, callback, min=1, max=100, step=1):
        self._min = min
        self._max = max
        self._step = step
        self._value_init = (min+max)/2
        self._id = "slider" + str(id(self))
        self._python_var = python_var
        self._callback = callback
        
    def update(self, value):
        return self._callback(value)
    
    def _repr_html_(self):
        javascript = """ \
<script type="text/Javascript">
    var %(id)s_computing = false;
    function %(id)s_updated(value, final) {
        //get the element
        var display = document.getElementById("chosen%(id)s");
        //show the amount
        display.innerHTML="%(python_var)s = " + value;
        var command = "%(python_var)s.update(" + value + ")";
        //console.log("Executing Command: " + command);
        
        var kernel = IPython.notebook.kernel;
        if (%(id)s_computing == false || final == true) {
            kernel.execute(command, {'output' : %(id)s_handle_output}, {silent:false});
            %(id)s_computing = true;
        }
    }
    function %(id)s_handle_output(out_type, out) {
        %(id)s_computing = false;
        //console.log(out_type);
        //console.log(out);
        var res = null;
         // if output is a print statement
        if(out_type == "stream"){
            res = out.data;
        }
        // if output is a python object
        else if(out_type === "pyout"){
            res = out.data["text/plain"];
            //FIXME: Comment out the next few lines for SymPy output
            document.getElementById("anim_frame%(id)s").src = res.substring(1, res.length - 1);
            res = "Image"
        }
        // if output is a python error
        else if(out_type == "pyerr"){
            res = out.ename + ": " + out.evalue;
        }
        // if output is something we haven't thought of
        else{
            res = "[out type not implemented]";   
        }
        document.getElementById("%(id)s_result_output").innerHTML = res;
    }
</script>
""" % {"id": self._id, "python_var": self._python_var}
        html = """ \
%(min)s <input id="%(id)s" type="range" min="%(min)s" max="%(max)s" step="%(step)s" value="%(value_init)s"
    onchange="%(id)s_updated(this.value, false)" onmouseup="%(id)s_updated(this.value, true)" /> %(max)s</div>
<div id="chosen%(id)s">%(python_var)s = %(value_init)s</div>
Result: <div id="%(id)s_result_output"></div>
<img id="anim_frame%(id)s" src=""><br>
""" % {"id": self._id, "min": self._min, "max": self._max, "step": self._step, "value_init": self._value_init,
        "python_var": self._python_var}
        return javascript + html

In [2]:
from vtk import (vtkSphereSource, vtkPolyDataMapper, vtkActor, vtkRenderer,
        vtkRenderWindow, vtkWindowToImageFilter, vtkPNGWriter, vtkStructuredGridReader, vtkPlane,
        vtkCutter, vtkDataSetMapper, vtkContourFilter, vtkCamera, vtkOutlineSource,
        vtkRectilinearGridReader, vtkLineSource, vtkProbeFilter, vtkDataObjectToTable)
from vtk.util.numpy_support import vtk_to_numpy
from numpy import array, linspace, sqrt
from pylab import plot

def vtk_show(renderer, w=100, h=100):
    """
    Takes vtkRenderer instance and returns an IPython Image with the rendering.
    """
    renderWindow = vtkRenderWindow()
    renderWindow.SetOffScreenRendering(1)
    renderWindow.AddRenderer(renderer)
    renderWindow.SetSize(w, h)
    renderWindow.Render()
     
    windowToImageFilter = vtkWindowToImageFilter()
    windowToImageFilter.SetInput(renderWindow)
    windowToImageFilter.Update()
     
    writer = vtkPNGWriter()
    writer.SetWriteToMemory(1)
    writer.SetInputConnection(windowToImageFilter.GetOutputPort())
    writer.Write()
    data = str(buffer(writer.GetResult()))
    
    from IPython.display import Image
    return Image(data)

def get_plane(r, n1, n2, n3):
    plane = vtkPlane()
    plane.SetOrigin(r.GetOutput().GetCenter())
    plane.SetNormal(n1, n2, n3)
    
    c = vtkCutter()
    c.SetInputConnection(r.GetOutputPort())
    c.SetCutFunction(plane)
    
    m = vtkPolyDataMapper()
    m.SetInputConnection(c.GetOutputPort())
    m.SetScalarRange(r.GetOutput().GetScalarRange()) 
    
    a = vtkActor()
    a.SetMapper(m)
    return a

def get_outline(r):
    s = vtkOutlineSource()
    s.SetBounds(r.GetOutput().GetBounds())
    m = vtkDataSetMapper()
    m.SetInputConnection(s.GetOutputPort())
    a = vtkActor()
    a.SetMapper(m)
    a.GetProperty().SetColor(0, 0, 0)
    return a

def get_contour(r):
    iso = vtkContourFilter()
    iso.SetInputConnection(r.GetOutputPort())
    rmin, rmax = r.GetOutput().GetScalarRange()
    iso.SetValue(0, (rmin+rmax)/2)
    #iso.SetValue(1, (rmin+rmax)/4)
    
    m = vtkPolyDataMapper()
    m.SetInputConnection(iso.GetOutputPort())
    m.SetScalarRange(r.GetOutput().GetScalarRange())
    a = vtkActor()
    a.SetMapper(m)
    return a

def get_renderer(l):
    renderer = vtkRenderer()
    for a in l:
        renderer.AddActor(a)
    renderer.SetBackground(1, 1, 1)
    return renderer

def line_values(r, a, b, n):
    a = array(a)
    b = array(b)
    line = vtkLineSource()
    line.SetPoint1(a)
    line.SetPoint2(b)
    line.SetResolution(n)
    probe = vtkProbeFilter()
    probe.SetInputConnection(line.GetOutputPort())
    probe.SetSourceData(r.GetOutput())
    dot = vtkDataObjectToTable()
    dot.SetInputConnection(probe.GetOutputPort())
    dot.Update()
    table = dot.GetOutput()
    x = linspace(0, sqrt(sum((a-b)**2)), n+1)
    y = vtk_to_numpy(table.GetColumn(0))
    return x, y

In [3]:
r = vtkRectilinearGridReader()
r.SetFileName("data/Venq.vtk")
r.Update()

renderer = get_renderer([
    get_plane(r, 1, 0, 0),
    get_plane(r, 0, 1, 0),
    get_plane(r, 0, 0, 1),
    get_outline(r),
    #get_contour(r),
    ])
    
camera = renderer.GetActiveCamera()
renderer.ResetCamera()
camera.Elevation(30)
camera.Azimuth(30)

vtk_show(renderer, 500, 500)


Out[3]:

In [4]:
def update(value):
    camera = vtkCamera()
    camera.Elevation(value)
    camera.Azimuth(30)
    renderer.SetActiveCamera(camera)
    renderer.ResetCamera()
    i = vtk_show(renderer, 500, 500)
    data = i.data.encode('base64')
    return "data:image/png;base64,{0}".format(data.replace('\n', ''))

s = Slider("s", update)
s


Out[4]:
1 100
s = 50
Result:


In [5]:
from sympy import var, factor
var("x")
def update(value):
    return factor(x**value-1)

t = Slider("t", update)
t


Out[5]:
1 100
t = 50
Result:


In [5]: