Search code examples
pythonpython-3.xmayavimayavi.mlab

Extracting data from Mayavi pipeline -- specifically coordinates for a point-defined-surface


I am running a script to create a cylindrical surface defined by a set of points. I am using Mayavi to render the visualizations. For the following script, how could I find the coordinates of each point? It seems like Mayavi is doing this behind the scenes in the data pipeline, but I am not too sure how to extract it. Alternatively, I tried doing nested for loops, but I haven't figured out the correct algorithm... I will keep trying in the meantime. However, if someone knows how to extract them from the Mayavi pipeline, that would be great since I won't have to add any more computation time.

import numpy as np
import mayavi
from mayavi import mlab

class cylinder:
  def __init__(self, radius, length):
    phi, x = np.mgrid[0:np.pi:50j, 0:length:50j]
    self.z = radius * np.sin(phi)
    self.y = radius * np.cos(phi)
    self.x = x
    self.mesh = mlab.points3d(self.x,self.y,self.z, mode = 'point')


def main():
  cylinder = cylinder(radius=1,length=2)
  mayavi.mlab.axes()
  mlab.show()


main()

Solution

  • All the data you pass to mayavi will be present in the corresponding data source. I'd note, however, that I wouldn't think that you'd often want to reverse-engineer your data from the pipeline, since it was you who passed those data in the first place (so you should be able to keep track of that data without having to dig down into the low-level vtk machinery).

    Anyway, assuming that you only have a single scene and a single data source in your pipeline:

    engine = mlab.get_engine()
    source = engine.scenes[0].children[0]
    # choose a scene among engine.scenes if necessary
    # choose a source among engine.scenes[0] if necessary
    
    points_data = np.array(source.data.points)
    

    In your specific example you passed three arrays of shape (50,50) to points3d. What we get for points_data is an array of shape (2500,3). Suspicious. Sure enough, we can reshape it into the appropriate shape in order to reconstruct the original data:

    x,y,z = points_data.T
    # x,y,z have shape (2500,) now, no way to know the "true" original shape
    
    # if we know what their shape _should_ be, we can fix that too:
    x,y,z = points.data.reshape(50,50,3).transpose(2,0,1)
    
    # compare to the original data
    radius,length = 1,2
    phi, x0 = np.mgrid[0:np.pi:50j, 0:length:50j]
    z0 = radius * np.sin(phi)
    y0 = radius * np.cos(phi)
    print(np.array_equal(x, x0)) # True
    print(np.array_equal(y, y0)) # True
    print(np.array_equal(z, z0)) # True
    

    Since the multidimensional structure of the input arrays is irrelevant to mayavi, I don't expect we can reconstruct the original x,y,z arrays with the right shape from the pipeline. If I were mayavi I'd ravel all the input arrays losing all possible multidimensional structure, and I'm pretty sure that's exactly what happens.