Question

I'm using python and mayavi2 for 3D plotting. I'm plotting a sphere using the mesh command, and now I want to color some of the panels of the sphere a different color. It seems like this is what the mask option is for, but I can't get it to work (I just get the whole sphere recolored).

http://docs.enthought.com/mayavi/mayavi/auto/mlab_helper_functions.html#mayavi.mlab.mesh "mask: boolean mask array to suppress some data points"

I use:

mesh(X,Y,Z, color = (1,1,1), opacity=0.5)

to color the whole sphere white, and then

mesh(X,Y,Z, color = (1,0,1), mask = active_region, opacity=0.5) 

to color some parts purple, where

active_region = [[False False False False False False  True]
                 [False False False False False False  True]
                 [False False False False False  True  True]
                 [False False False  True  True  True  True]
                 [False False  True  True  True  True  True]
                 [False False False  True  True  True  True]
                 [False False False False False False  True]]

but this results in a completely purple sphere. X, Y, and Z are all arrays with shape (7,7), just like active_region. What am I doing wrong?

Was it helpful?

Solution

Masking works based on scalars and not when you have set a solid color. Try this instead:

import numpy as np
m = mesh(X,Y,Z, mask=active_region, opacity=0.5)
m.mlab_source = ones_like(X)

The masking works by setting the scalar to Nan where masked. The geometry drawn is the same but the masked regions are not displayed if the scalars are Nan's.

In any case, here is a complete working example for your reference:

import numpy as np
phi, theta = np.mgrid[0:np.pi:100j, 0:2 * np.pi:100j]
x = np.sin(phi) * np.cos(theta)
y = np.sin(phi) * np.sin(theta)
z = np.cos(phi)
mask = np.zeros_like(x).astype(bool)
mask[::5] = True
mask[:,::5] = True

from mayavi import mlab
mlab.mesh(x, y, z, scalars=z, mask=mask)

Note that you don't need to provide the scalars, its just that if you provide an explicit color there will be no masking. Also the scalars here are simply set to z you can use any compatible array, even a constant value via ones_like(X).

Turns out that if you have a constant scalar VTK 5.6 doesn't seem to mask your points correctly, if you have VTK 5.10 you can do the following:

m = mlab.mesh(x, y, z, scalars=scalars, mask=mask)
m.module_manager.scalar_lut_manager.lut.nan_color = 0, 0, 0, 0

Otherwise, use scalar=z and setup a constant color lookup table. You can create your own by clicking on "colors and legends" on the pipeline editor, then click on "launch lut editor". To use this custom color map, do the following:

scalars = np.ones_like(x)
m = mlab.mesh(x, y, z, scalars=scalars, mask=mask)
m.module_manager.scalar_lut_manager.lut_mode = 'file'
m.module_manager.scalar_lut_manager.file_name = '/path/to/your.lut'

If you do not want to mess with the LUT editor and all that malarky, here is a pure numpy version that you can do right from Python.

m = mlab.mesh(x, y, z, scalars=z, mask=mask)
# Lets make some colors:
#    this is an array of (R, G, B, A) values (each in range 0-255), there should
#    be at least 2 colors in the array.
colors = np.zeros((2, 4), dtype='uint8')
# Set the green value to constant.
colors[:,1] = 255
# the alpha value to fully opaque.
colors[:,3] = 255
# Now use this colormap.
m.module_manager.scalar_lut_manager.lut.table = colors

Note that the colors array should have at least 2 colors and can have as many as you like. For a constant color 2 should suffice.

HTH.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top