[vtkusers] Strange segfault (wxPython + wxVTKRenderWindowInteractor + widget)

Paul Melis paul at science.uva.nl
Wed Mar 7 07:18:11 EST 2007


Hello,

I'm trying to use one of the 3D VTK widgets in a wxPython application. I 
originally stumbled upon the segfault described below while trying to 
use a vtkImagePlaneWidget, but found that vtkBoxWidget and 
vtkSphereWidget also show the same problem. I include here a stripped 
version of my original app for easy demonstration. This is all with a 
recent CVS version of VTK, wxPython 2.6.3 and Python 2.4.3 on Fedora Core 4.

The code below derives a custom frame from wx.Frame, places a button and 
a wxVTKRenderWindowInteractor on that frame. The standard headsq/quarter 
VTK dataset is loaded when the button is pressed and a volume rendering 
is set up using the dataset. A wx.App is created that creates the frame 
and then runs the application main loop. This all works as expected, the 
volume is rendered and can be rotated, zoomed, etc.

Problems start when adding a vtkImagePlaneWidget to the pipeline, so as 
to show image slices of the data set. The addition of the widget in the 
code below is guarded with an "if False:", but changing to True will add 
the widget and set its interactor to the wxVTKRenderWindowInteractor of 
the frame. The widget is then placed with PlaceWidget() and enabled with 
On(). When the app is run with the widget enabled then any mouse 
interaction after the dataset is loaded will cause a segfault. The 
relevant (top) part of the stack trace is:

#0  0x00000000 in ?? ()
#1  0x04543d87 in vtkImagePlaneWidget::ProcessEvents () from 
/home/paul/vtk/bin/libvtkWidgets.so.5.1
#2  0x055989c1 in vtkCallbackCommand::Execute () from 
/home/paul/vtk/bin/libvtkCommon.so.5.1
#3  0x0561289a in vtkSubjectHelper::InvokeEvent () from 
/home/paul/vtk/bin/libvtkCommon.so.5.1
#4  0x05612904 in vtkObject::InvokeEvent () from 
/home/paul/vtk/bin/libvtkCommon.so.5.1
#5  0x023af093 in vtkGenericRenderWindowInteractor::LeftButtonPressEvent 
() from /home/paul/vtk/bin/libvtkRendering.so.5.1
#6  0x03026dd4 in 
PyvtkGenericRenderWindowInteractor_LeftButtonPressEvent () from 
/home/paul/vtk/bin/libvtkRenderingPythonD.so.5.1
#7  0x003106c3 in PyCFunction_Call () from /usr/lib/libpython2.4.so.1.0
#8  0x0034931c in PyEval_EvalFrame () from /usr/lib/libpython2.4.so.1.0
#9  0x0034aa1c in PyEval_EvalCodeEx () from /usr/lib/libpython2.4.so.1.0
#10 0x002ff0b1 in PyFunction_SetClosure () from /usr/lib/libpython2.4.so.1.0
#11 0x002ea7c6 in PyObject_Call () from /usr/lib/libpython2.4.so.1.0
#12 0x002f20ee in PyMethod_Fini () from /usr/lib/libpython2.4.so.1.0
#13 0x002ea7c6 in PyObject_Call () from /usr/lib/libpython2.4.so.1.0
#14 0x00343b1c in PyEval_CallObjectWithKeywords () from 
/usr/lib/libpython2.4.so.1.0
#15 0x004be8de in wxPyCallback::EventThunker () from 
/usr/lib/python2.4/site-packages/wx-2.6-gtk2-unicode/wx/_core_.so
#16 0x009fed3d in wxAppConsole::HandleEvent () from 
/usr/lib/libwx_baseu-2.6.so.0
#17 0x00a87c7f in wxEvtHandler::ProcessEventIfMatches () from 
/usr/lib/libwx_baseu-2.6.so.0
#18 0x00a87d40 in wxEvtHandler::SearchDynamicEventTable () from 
/usr/lib/libwx_baseu-2.6.so.0
#19 0x00a87fe5 in wxEvtHandler::ProcessEvent () from 
/usr/lib/libwx_baseu-2.6.so.0
#20 0x00f07fda in wxWinModule::wxCreateObject () from 
/usr/lib/libwx_gtk2u_core-2.6.so.0
[...]

There seems to be a null pointer being used somewhere, but looking at 
vtkImagePlaneWidget::ProcessEvents() the only candidate for that would 
be the parameter "clientdata" as it is the only one used in the method. 
This is so deep within VTK that I don't know what's going on. Perhaps 
I'm setting things up slightly wrong or maybe there's a problem with the 
wxVTKRenderWindowInteractor.

Any help would be greatly appreciated,
Paul

===============================
#!/usr/bin/env python
import sys
import wx

import vtk
from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor

from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()

class MainFrame(wx.Frame):
   
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title)
       
        self.button = wx.Button(self, -1, "Load!")       
        self.button.SetDefault()
        self.Bind(wx.EVT_BUTTON, self.OnLoad, self.button)

        self.vtk_widget = wxVTKRenderWindowInteractor(self, -1, 
size=wx.Size(800,600))       
        self.vtk_widget.Enable(1)                   
           
        sizer = wx.BoxSizer(wx.VERTICAL)       
        sizer.Add(self.button, 0, wx.EXPAND)
        sizer.Add(self.vtk_widget, 1, wx.EXPAND|wx.ALL, 1)       
       
        self.CreateStatusBar()
        self.SetStatusText("")
       
        self.vtk_renderer = vtk.vtkRenderer()
        self.vtk_renderer.AddObserver("StartEvent", lambda o,e: 
self.OnRenderingStart(o,e))
        self.vtk_renderer.AddObserver("EndEvent", lambda o,e: 
self.OnRenderingEnd(o,e))       
       
        self.vtk_widget.GetRenderWindow().AddRenderer(self.vtk_renderer)
       
        self.SetSizer(sizer)
        sizer.SetSizeHints(self)   

    def OnRenderingStart(self, obj, evt):
        self.SetStatusText("Rendering")
        self.Update()
        wx.Yield()       
       
    def OnRenderingEnd(self, obj, evt):
        self.SetStatusText("")
        self.Update()
        wx.Yield()       
       
    def OnLoad(self, evt):

        # Load a volume, use the widget to control what's volume
        # rendered. Basically the idea is that the vtkBoxWidget provides 
a box
        # which clips the volume rendering.
        v16 = vtk.vtkVolume16Reader()
        v16.SetDataDimensions(64, 64)
        v16.GetOutput().SetOrigin(0.0, 0.0, 0.0)
        v16.SetDataByteOrderToLittleEndian()
       
        v16.SetFilePrefix(VTK_DATA_ROOT+ "/Data/headsq/quarter")
        v16.SetImageRange(1, 93)
        v16.SetDataSpacing(3.2, 3.2, 1.5)
               
        print "scalar range:", v16.GetOutput().GetScalarRange()

        tfun = vtk.vtkPiecewiseFunction()
        tfun.AddPoint(70.0, 0.0)
        tfun.AddPoint(599.0, 0)
        tfun.AddPoint(600.0, 0)
        tfun.AddPoint(1195.0, 0)
        tfun.AddPoint(1200, .2)
        tfun.AddPoint(1300, .3)
        tfun.AddPoint(2000, .3)
        tfun.AddPoint(4095.0, 1.0)

        ctfun = vtk.vtkColorTransferFunction()
        ctfun.AddRGBPoint(0.0, 0.5, 0.0, 0.0)
        ctfun.AddRGBPoint(600.0, 1.0, 0.5, 0.5)
        ctfun.AddRGBPoint(1280.0, 0.9, 0.2, 0.3)
        ctfun.AddRGBPoint(1960.0, 0.81, 0.27, 0.1)
        ctfun.AddRGBPoint(4095.0, 0.5, 0.5, 0.5)

        compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()

        volumeMapper = vtk.vtkVolumeRayCastMapper()
        volumeMapper.SetInputConnection(v16.GetOutputPort())
        volumeMapper.SetVolumeRayCastFunction(compositeFunction)

        volumeProperty = vtk.vtkVolumeProperty()
        volumeProperty.SetColor(ctfun)
        volumeProperty.SetScalarOpacity(tfun)
        volumeProperty.SetInterpolationTypeToLinear()
        volumeProperty.ShadeOn()

        newvol = vtk.vtkVolume()
        newvol.SetMapper(volumeMapper)
        newvol.SetProperty(volumeProperty)
       
        self.vtk_renderer.AddVolume(newvol)
        self.vtk_renderer.SetBackground(0, 0, 0)

        # Show an outline (box)
        if False:           
            outline = vtk.vtkOutlineFilter()
            outline.SetInputConnection(v16.GetOutputPort())
            outlineMapper = vtk.vtkPolyDataMapper()
            outlineMapper.SetInputConnection(outline.GetOutputPort())
            outlineActor = vtk.vtkActor()
            outlineActor.SetMapper(outlineMapper)
            self.vtk_renderer.AddActor(outlineActor)                       
               
        # vtkImagePlaneWidget
        if False:
            ipw = vtk.vtkImagePlaneWidget()       
            ipw.SetInput(v16.GetOutput())                       
            ipw.SetPlaneOrientationToXAxes()
            ipw.SetSliceIndex(1)
            ipw.DisplayTextOn()
           
            picker = vtk.vtkCellPicker()
            ipw.SetPicker(picker)
           
            ipw.SetInteractor(self.vtk_widget._Iren)               
            ipw.PlaceWidget()
            ipw.On()
           
        # vtkSphereWidget
        if False:
            w = vtk.vtkSphereWidget()
            w.SetInput(v16.GetOutput())
            w.SetInteractor(self.vtk_widget._Iren)
            w.PlaceWidget()
            w.On()

class MyApp(wx.App):
   
    def OnInit(self):
        frame = MainFrame(None, "VTK")               

        self.SetTopWindow(frame)
        frame.Show(True)

        return True

app = MyApp(redirect=False)

app.MainLoop()

==========================





More information about the vtkusers mailing list