enthought / mayavi

3D visualization of scientific data in Python
http://docs.enthought.com/mayavi/mayavi/
Other
1.32k stars 286 forks source link

Was picker type=cell ported to Mayavi 4.0.0? #21

Closed mattions closed 12 years ago

mattions commented 12 years ago

I've just upgraded to Mayavi 4.0.0 and I've discovered that the picker type=cell doesn't work. to be precise is the line:

    picker = figure.on_mouse_pick(picker_callback, type='cell')

For example, try to use it with the redball example:

# Author: Gael Varoquaux <gael dot varoquaux at normalesup.org>
# Copyright (c) 2009, Enthought, Inc.
# License: BSD style.

import numpy as np
from mayavi import mlab

################################################################################
# Disable the rendering, to get bring up the figure quicker:
figure = mlab.gcf()
mlab.clf()
figure.scene.disable_render = True

# Creates two set of points using mlab.points3d: red point and
# white points
x1, y1, z1 = np.random.random((3, 10))
red_glyphs = mlab.points3d(x1, y1, z1, color=(1, 0, 0),
                resolution=20)

x2, y2, z2 = np.random.random((3, 10))
white_glyphs = mlab.points3d(x2, y2, z2, color=(0.9, 0.9, 0.9),
                resolution=20)

# Add an outline to show the selected point and center it on the first
# data point.
outline = mlab.outline(line_width=3)
outline.outline_mode = 'cornered'
outline.bounds = (x1[0]-0.1, x1[0]+0.1,
                  y1[0]-0.1, y1[0]+0.1,
                  z1[0]-0.1, z1[0]+0.1)

# Every object has been created, we can reenable the rendering.
figure.scene.disable_render = False
################################################################################

# Here, we grab the points describing the individual glyph, to figure
# out how many points are in an individual glyph.
glyph_points = red_glyphs.glyph.glyph_source.glyph_source.output.points.to_array()

def picker_callback(picker):
    """ Picker callback: this get called when on pick events.
    """
    if picker.actor in red_glyphs.actor.actors:
        # Find which data point corresponds to the point picked:
        # we have to account for the fact that each data point is
        # represented by a glyph with several points
        point_id = picker.point_id/glyph_points.shape[0]
        # If the no points have been selected, we have '-1'
        if point_id != -1:
            # Retrieve the coordinnates coorresponding to that data
            # point
            x, y, z = x1[point_id], y1[point_id], z1[point_id]
            # Move the outline to the data point.
            outline.bounds = (x-0.1, x+0.1,
                              y-0.1, y+0.1,
                              z-0.1, z+0.1)

picker = figure.on_mouse_pick(picker_callback, type='cell')

# Decrease the tolerance, so that we can more easily select a precise
# point.
picker.tolerance = 0.01

mlab.title('Click on red balls')

mlab.show()

I'm getting this error:

mattions@triton:examples(master*)$ python select_red_balls.py 
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/mayavi/core/mouse_pick_dispatcher.py", line 168, in on_button_release
    picker.pick((x, y, 0), self.scene.scene.renderer)
  File "tvtk_classes/abstract_picker.py", line 153, in pick
  File "/usr/local/lib/python2.7/dist-packages/tvtk/tvtk_base.py", line 523, in _wrap_call
    ret = vtk_method(*args)
TypeError: function takes exactly 4 arguments (2 given)

It worked before with 3.6.0

mattions commented 12 years ago

Adding an idea from Gael here:

Bug #21: figure out which call in VTK has changed signature, and what is the new signature. For this inspect the call stack using pdb to see where 'vtk_method' comes from when the error is raised, then look at the online VTK reference and see what is the more recent signature of this VTK method, finally implement both options in abstract_picker, with a try/except.

GaelVaroquaux commented 12 years ago

I can't replicate this bug either. What's your VTK version?

mattions commented 12 years ago

I have VTK 5.6.1

Which is yours?

mattions commented 12 years ago

I'm trying to get a bit more a clear view into this and I think I've got a lead:

This is the current stack trace:

mtime: 814019.Print the args passed to the picker:
((105, 134, 0), <libvtkRenderingPython.vtkOpenGLRenderer vtkobject at 0x769da20>)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/mattions/.virtualenvs/mayavi_git/src/mayavi/mayavi/core/mouse_pick_dispatcher.pyc in on_button_release(self, vtk_picker, event)
    166             x, y = vtk_picker.GetEventPosition()
    167             for picker in self._active_pickers.values():
--> 168                 picker.pick((x, y, 0), self.scene.scene.renderer)
    169         self._mouse_no_mvt = 0
    170 

/home/mattions/.virtualenvs/mayavi_git/src/mayavi/tvtk/tvtk_classes.zip/tvtk_classes/abstract_picker.pyc in pick(self, *args)
    151         """
    152         my_args = [deref_vtk(x) for x in args]
--> 153         ret = self._wrap_call(self._vtk_obj.Pick, *my_args)
    154         return ret
    155 

/home/mattions/.virtualenvs/mayavi_git/src/mayavi/tvtk/tvtk_base.py in _wrap_call(self, vtk_method, *args)
    523         print("mtime: %s.Print the args passed to the picker:" %mtime)
    524         print(args)
--> 525         ret = vtk_method(*args)
    526         self._in_set -= 1
    527         if self._wrapped_mtime(vtk_obj) > mtime:

TypeError: function takes exactly 4 arguments (2 given)

which means there is something going on in the zipped class. I've extracted and I found on the doc:

def pick(self, *args):
        """
        V.pick(float, float, float, Renderer) -> int
        V.pick((float, float, float), Renderer) -> int
        return this Pick selectionPt selectionPt selectionPt ren 
         Perform pick operation with selection point provided. Normally the 
         first two values for the selection point are x-y pixel coordinate, and
         the third value is =0. Return non-zero if something was successfully 
         picked.
        """
        my_args = [deref_vtk(x) for x in args]
        ret = self._wrap_call(self._vtk_obj.Pick, *my_args)
        return ret

So the method should exists, however the selection for the methods is somehow wrong. The first one is used and therefore I get the error.

Any idea about this?

mattions commented 12 years ago

If I pass the single coordinates instead of the tuple, I get this working

from

picker.pick((x, y, 0), self.scene.scene.renderer)

to

picker.pick(x, y, 0, self.scene.scene.renderer)

Should I open a pull request to have it in this format?

GaelVaroquaux commented 12 years ago

On Wed, Feb 08, 2012 at 03:36:33AM -0800, Michele Mattioni wrote:

Should I open a pull request to have it in this format?

Yes, with a try/except trying the current solution, and if it fails with the exception that is currently been raised, trying the other.

Thanks

mattions commented 12 years ago

I've update the pull request #23 with the try except clause https://github.com/mattions/mayavi/commit/4ffeaabeb9a9b827eed7bd856bc1c1eb59ac07c6

It should merge without trouble. Works here.

mattions commented 12 years ago

taken car in pull #23