enthoughtmayavimayavi.mlabvolume-rendering

Mayavi volume does not render colors, until altered interactively. Thus can't save in the batch mode


I am working on a 3D visualization, in which I would like to mark part of the space, thus drawing something like a semi-transparent cloud in a given color.

I was googling for recipes and here is what I came up with. I try to make this cloud in a shape of a cube that would be green and half-transparent.

from mayavi import mlab
import numpy as np

def plot_volume():
    # space 10 x 10 x 10 voxels, all have value = 0
    s = np.zeros((10, 10, 10))
    # now 64 voxels inside have value = 1
    s[3:7:1, 3:7:1, 3:7:1] = 1
    # we cut one corner to see if it will be asymmetric
    s[3,3,3] = 0
    fig = mlab.figure()
    # This I do according to http://docs.enthought.com/mayavi/mayavi/auto/mlab_pipeline_sources.html#mayavi.tools.pipeline.scalar_field
    sf = mlab.pipeline.scalar_field(s)
    vol = mlab.pipeline.volume(sf)
    # If I understand well, I should have volume with scalar values now
    # What remains is manipulating its colors and opacity
    # I take the recipie from here: http://docs.enthought.com/mayavi/mayavi/auto/mlab_pipeline_other_functions.html#volume
    from tvtk.util.ctf import ColorTransferFunction
    ctf = ColorTransferFunction()
    # all points with value = 1 should be green
    ctf.add_rgb_point(1, 0, 1, 0)   
    vol._volume_property.set_color(ctf)
    vol._ctf = ctf
    vol.update_ctf = True
    # opacity
    from tvtk.util.ctf import PiecewiseFunction
    otf = PiecewiseFunction()
    # all points with value = 1 should be semi-transparent
    otf.add_point(1, 0.5)
    # all points with value = 0 should not be visible at all
    otf.add_point(0, 0)
    vol._otf = otf
    vol._volume_property.set_scalar_opacity(otf)
    mlab.savefig('volume_auto.png')
    mlab.show()

Basically, I am modifying examples from these two links: how to create a volume from scalar field and howto color it.

Sadly, the result is far from my expectation. The automatically saved figure looks like this:

enter image description here

Thus, the green color is not rendered at all. If I display the same thing in an interactive window, rotate it a bit, then the color appears:

enter image description here

But it is still far from perfect, instead of a green cubic cloud with a cut corner, I see a black cube with a cut corner, surrounded by a green mist. EDIT: this part of the problem is solved, when the non-zero value used is 255 instead of 1.

I would love to know how to fix these two problems and also I am happy not to use the volume, if there is a better way to plot a cloud I want. I tried plotting it with a bunch of cubes, like 3D pixels, it works fine, but is super slow, as many cube objects are created and the effect is like a video game from the 80'. I use mayavi 4.8.0.


Solution

  • OK, to solve it, one needs to do two things:

    1. use mlab.options.offscreen = True. Solves the first problem I described (now green will be visible without interactive intervention).
    2. stretch the values in the volume exactly between 0 and 255. I found it here after posting my question. Now the cube will be really green, not black with a mist:

    enter image description here

    Weirdly enough, when calling ctf.add_rgb_point(value, ...) we still need to do value = 1, which I don't understand.