Search code examples
python3dmayavimayavi.mlab

Combining multiple plots with mayavi


I have a 3D contour plot, which I make with python's mayavi library, into which I want to overplot some arrows. For the contour plot I use mlab.contour3d and for the arrow mlab.quiver3d (link to the mlab docs, to quiver3d, to contour3d). To make the example easy, I use a sphere for the contour here. It works fine as long as I plot both things separately, i.e. in different runs, see the following plot.

Two separated plots

When I try to combine both plots, however, it is not working properly, the coordinates of both plots seem not to match, see the following plot where the arrow is somewhere very small in the bottom left corner. I have also no idea what happened to the axes and their labels.

combined plots

This is my code:

import numpy as np
from mayavi import mlab

# starting coordinates of vector
x = np.array([2.])
y = np.array([1.])
z = np.array([0.])

# components for vectors
u = np.array([3.])
v = np.array([0.])
w = np.array([0.])

# making 3D arrays for quiver3d
XX, YY, ZZ = np.meshgrid(x, y, z)
UU, VV, WW = np.meshgrid(u, v, w)

# coordinates for caluclating the sphere
x_arr = np.linspace(0,5,50)
y_arr = np.linspace(0,5,50)
z_arr = np.linspace(0,5,50)

# center and radius of sphere
xc = 2
yc = 2.5
zc = 3
r  = 2

# make the sphere
data2plot = np.zeros( (len(x_arr), len(y_arr), len(z_arr)) )
for ii in range(len(x_arr)):
    for jj in range(len(y_arr)):
        for kk in range(len(z_arr)):
            if np.sqrt( (x_arr[ii]-xc)**2 
                       +(y_arr[jj]-yc)**2 
                       +(z_arr[kk]-zc)**2 ) < r:
                data2plot[ii,jj,kk] = 1


fig1 = mlab.figure( bgcolor=(1,1,1), fgcolor=(0,0,0))

# contour plot and arrow-plot, separately, they work, combined not
xx_arr, yy_arr, zz_arr = np.meshgrid(x_arr, y_arr, z_arr, indexing='ij')
contPlot = mlab.contour3d( xx_arr, yy_arr, zz_arr, data2plot, 
                           transparent=True, opacity=.4, figure=fig1)
arrowPlot = mlab.quiver3d(XX, YY, ZZ, UU, VV, WW, 
                          line_width=1, mode='arrow', figure=fig1 )

ax1 = mlab.axes( color=(1,1,1), nb_labels=4 )

mlab.show()

Any hint on what I am missing or doing wrong is greatly appreciated!


Solution

  • In principle, my code above was working, the weird looking sizes, comparing the arrow with the sphere, seems to be due to the perspective. The code had some flaws though concerning the axes. This is the updated part:

    # explicitly define the extent of the axes
    ax1 = mlab.axes( nb_labels=4,
                     extent=[0, xc+r,
                             0, yc+r,
                             0, zc+r, ],
                   )
    
    # to not only have the axes around one of the drawn objects
    mlab.outline(ax1)
    

    The results looks as follows: enter image description here