python-2.7traitsmayavitraitsuimayavi.mlab

Mayavi: Get array index from picker object


In the mayavi application coded below I'm trying to obtain the array index of the plotted example data set. I'm following the picker example on the web very closely but in this class implementation it doesn't seem to work, see the code comments where it fails. The picker example on the web does work, also on my system. Any help would be much appreciated.

import numpy as np

from traits.api import HasTraits, Instance, Button, on_trait_change
from traitsui.api import View, Item

from mayavi.core.ui.api import SceneEditor, MayaviScene, MlabSceneModel



# Create some example data
def getData():
    dataPoints = np.array([[ 0,  0, 1],
                         [-1, -1, 0],
                         [ 1, -1, 0],
                         [-1,  1, 0],
                         [ 1,  1, 0]], dtype=np.float64)

    return (dataPoints[:,0], dataPoints[:,1], dataPoints[:,2])


#------------------------------------------------------------------------------


# The dialog object
class DataInspector(HasTraits):

    # The view displayed
    scene3d = Instance(MlabSceneModel, ())

    # The buttons
    button1 = Button('SetToMode1')
    button2 = Button('SetToMode2')
    button3 = Button('SetToMode3')



    # init constructor
    def __init__(self, **traits):
        super(DataInspector, self).__init__(**traits)

        # Set the mode to zero initially
        self.mode = 0

        # Get a simple dataset of five points
        (x, y, z) = getData()

        #----------------------------------------------
        # ADAPTED FROM "SELECT_RED_BALLS.PY" EXAMPLE
        #----------------------------------------------
        self.red_glyphs = self.scene3d.mlab.points3d(x, y, z, figure=self.scene3d.mayavi_scene, color=(1, 0, 0), resolution=20)
        #self.glyph_points = self.red_glyphs.glyph.glyph_source.glyph_source.output.points.to_array()

        #----------------------------------------------
        # THE COMMENTED LINE DOESN'T WORK. THE INTERPRETER COMPLAINS A NONE TYPE DOESN'T HAVE
        # A TO_ARRAY() METHOD. GOING ON ONE FINDS THAT .OUTPUT DOESN'T HAVE A .POINTS ATTRIBUTE.

        # ANYBODY NOTICING WHAT I'M DOING WRONG HERE AND WHY IT DOES WORK WITH IN
        # THE "SELECT_RED_BALLS.PY" EXAMPLE (ALSO ON MY MACHINE)???

        # COULD IT BE DUE TO THE FACT THAT MLAB IS AVAILABLE THROUGH MLABSCENEMODEL????
        #----------------------------------------------



    # Set up a picker when the scene has become active
    @on_trait_change('scene3d.activated')
    def initializePicker(self):
        picker = self.scene3d.mayavi_scene.on_mouse_pick(self.picker_callback)
        picker.tolerance = 0.01



    # Picker callback function
    def picker_callback(self, picker):
        if self.mode==1:
            print "Picked in mode 1..."
        elif self.mode==2:
            print "Picked in mode 2..."
        elif self.mode==3:
            print "Picked in mode 3..."
        else:
            print "Picked in unselected mode..."

        self.get_pickedArrayIndex(picker)


    def get_pickedArrayIndex(self, picker):

        #----------------------------------------------
        # ADAPTED FROM "SELECT_RED_BALLS.PY" EXAMPLE
        #----------------------------------------------

        print "This is a glyph component id " + str(picker.point_id) + " ????"
        print "Failing in get_pickedArrayIndex() because of glyph_points object..."

#       if picker.actor in self.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/self.glyph_points.shape[0]
#           # If the no points have been selected, we have '-1'
#           if point_id != -1:
#               print point_id
#
#               #----------------------------------------------
#               # I AM TRYING TO GET THE PICKED ARRAY INDEX AVAILABLE HERE
#               #----------------------------------------------




    @on_trait_change('button1')
    def set_mode1(self):
        self.mode = 1
        print "Mode set to 1"

    @on_trait_change('button2')
    def set_mode2(self):
        self.mode = 2
        print "Mode set to 2"

    @on_trait_change('button3')
    def set_mode3(self):
        self.mode = 3
        print "Mode set to 3"




    #----------------------------------------------------------------------------
    # The dialog layout
    #----------------------------------------------------------------------------
    view = View(Item('scene3d', editor=SceneEditor(), height=500, width=700, show_label=False),
              Item('button1', show_label=False),
              Item('button2', show_label=False),
              Item('button3', show_label=False),
              resizable=True,
              title='DataInspector'
             )




d = DataInspector()
d.configure_traits()

Solution

  • Nailed it in the end:

    The trick is to put the line

    self.glyph_points = self.red_glyphs.glyph.glyph_source.glyph_source.output.points.to_array()
    

    in the method where the picker gets initialized after a @on_trait_change('scene3d.activated')

    Apparently the .output.points are not available until the scene has become active(?)